├── releases ├── Arcade-DigDug_20190921.rbf ├── Arcade-DigDug_20191022.rbf ├── rommap.txt └── Dig Dug.mra ├── .gitignore ├── sys ├── pll_hdmi │ ├── pll_hdmi_0002.qip │ ├── pll_hdmi_0002_q13.qip │ └── pll_hdmi_0002.v ├── pll │ ├── pll_0002.qip │ └── pll_0002.v ├── sigma_delta_dac.v ├── pll_hdmi_q13.qip ├── scanlines.v ├── i2c.v ├── sys_top.sdc ├── video_cleaner.sv ├── sys.qip ├── build_id.tcl ├── sys_q13.qip ├── i2s.v ├── vga_out.sv ├── alsa.sv ├── video_mixer.sv ├── pll_hdmi_cfg.v ├── scandoubler.v ├── osd.v ├── pll_hdmi_cfg.qip ├── pll_hdmi_cfg │ └── altera_std_synchronizer.v ├── hdmi_config.sv ├── pll_hdmi_adj.vhd ├── sysmem.sv ├── hq2x.sv └── spdif.v ├── src ├── LINEBUF.qip ├── cpucore.v ├── dprams.v ├── cpu │ ├── tv80_reg.v │ ├── tv80s.v │ └── tv80_alu.v ├── DIGDUG_SPRITE.v ├── FPGA_DIGDUG.v ├── DIGDUG_VIDEO.v ├── wsg.v ├── DIGDUG_CORES.v ├── DIGDUG_IODEV.v ├── DIGDUG_CUSIO.v └── LINEBUF.v ├── clean.bat ├── Arcade-DigDug.qpf ├── readme.txt ├── Arcade-DigDug.srf └── Arcade-DigDug.sv /releases/Arcade-DigDug_20190921.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrX-8B/MiSTer-Arcade-DigDug/HEAD/releases/Arcade-DigDug_20190921.rbf -------------------------------------------------------------------------------- /releases/Arcade-DigDug_20191022.rbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MrX-8B/MiSTer-Arcade-DigDug/HEAD/releases/Arcade-DigDug_20191022.rbf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.bak 3 | db/* 4 | incremental_db/* 5 | output_files/* 6 | build_id.v 7 | jtag.cdf 8 | c5_pin_model_dump.txt 9 | *.qws 10 | -------------------------------------------------------------------------------- /sys/pll_hdmi/pll_hdmi_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name UNFORCE_MERGE_PLL_OUTPUT_COUNTER ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 3 | -------------------------------------------------------------------------------- /src/LINEBUF.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "17.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "LINEBUF.v"] 5 | -------------------------------------------------------------------------------- /releases/rommap.txt: -------------------------------------------------------------------------------- 1 | 2 | 0000-3FFF cpu0 3 | 4000-7FFF spchip 4 | 8000-9FFF cpu1 5 | A000-AFFF cpu2 6 | B000-BFFF bgscrn 7 | C000-CFFF bgchip 8 | D000-D7FF fgchip 9 | D800-D8FF wave 10 | D900-D9FF spclut 11 | DA00-DAFF bgclut 12 | DB00-DB1F palet 13 | 14 | [EOF] 15 | -------------------------------------------------------------------------------- /sys/pll/pll_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" 2 | 3 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /sys/pll_hdmi/pll_hdmi_0002_q13.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 2 | set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 3 | set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | del /s *.bak 3 | del /s *.orig 4 | del /s *.rej 5 | del /s *~ 6 | rmdir /s /q db 7 | rmdir /s /q incremental_db 8 | rmdir /s /q output_files 9 | rmdir /s /q simulation 10 | rmdir /s /q greybox_tmp 11 | rmdir /s /q hc_output 12 | rmdir /s /q .qsys_edit 13 | rmdir /s /q hps_isw_handoff 14 | rmdir /s /q sys\.qsys_edit 15 | rmdir /s /q sys\vip 16 | cd sys 17 | for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" 18 | cd .. 19 | for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" 20 | del build_id.v 21 | del c5_pin_model_dump.txt 22 | del PLLJ_PLLSPE_INFO.txt 23 | del /s *.qws 24 | del /s *.ppf 25 | del /s *.ddb 26 | del /s *.csv 27 | del /s *.cmp 28 | del /s *.sip 29 | del /s *.spd 30 | del /s *.bsf 31 | del /s *.f 32 | del /s *.sopcinfo 33 | del /s *.xml 34 | del *.cdf 35 | del /s new_rtl_netlist 36 | del /s old_rtl_netlist 37 | del sys\vip.qip 38 | del sys\sysmem.qip 39 | del sys\sdram.sv 40 | del sys\ddram.sv 41 | pause 42 | -------------------------------------------------------------------------------- /sys/sigma_delta_dac.v: -------------------------------------------------------------------------------- 1 | // 2 | // PWM DAC 3 | // 4 | // MSBI is the highest bit number. NOT amount of bits! 5 | // 6 | module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1) 7 | ( 8 | output reg DACout, //Average Output feeding analog lowpass 9 | input [MSBI:0] DACin, //DAC input (excess 2**MSBI) 10 | input CLK, 11 | input RESET 12 | ); 13 | 14 | reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder 15 | reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder 16 | reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder 17 | reg [MSBI+2:0] DeltaB; //B input of Delta Adder 18 | 19 | always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); 20 | always @(*) DeltaAdder = DACin + DeltaB; 21 | always @(*) SigmaAdder = DeltaAdder + SigmaLatch; 22 | 23 | always @(posedge CLK or posedge RESET) begin 24 | if(RESET) begin 25 | SigmaLatch <= 1'b1 << (MSBI+1); 26 | DACout <= INV; 27 | end else begin 28 | SigmaLatch <= SigmaAdder; 29 | DACout <= SigmaLatch[MSBI+2] ^ INV; 30 | end 31 | end 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /sys/pll_hdmi_q13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" 3 | set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] 5 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 6 | 7 | set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] 8 | set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] 9 | set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002_q13.qip"] 10 | 11 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" 12 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" 13 | set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" 14 | -------------------------------------------------------------------------------- /sys/scanlines.v: -------------------------------------------------------------------------------- 1 | module scanlines #(parameter v2=0) 2 | ( 3 | input clk, 4 | 5 | input [1:0] scanlines, 6 | input [23:0] din, 7 | output reg [23:0] dout, 8 | input hs,vs 9 | ); 10 | 11 | reg [1:0] scanline; 12 | always @(posedge clk) begin 13 | reg old_hs, old_vs; 14 | 15 | old_hs <= hs; 16 | old_vs <= vs; 17 | 18 | if(old_hs && ~hs) begin 19 | if(v2) begin 20 | scanline <= scanline + 1'd1; 21 | if (scanline == scanlines) scanline <= 0; 22 | end 23 | else scanline <= scanline ^ scanlines; 24 | end 25 | if(old_vs && ~vs) scanline <= 0; 26 | end 27 | 28 | wire [7:0] r,g,b; 29 | assign {r,g,b} = din; 30 | 31 | always @(*) begin 32 | case(scanline) 33 | 1: // reduce 25% = 1/2 + 1/4 34 | dout = {{1'b0, r[7:1]} + {2'b00, r[7:2]}, 35 | {1'b0, g[7:1]} + {2'b00, g[7:2]}, 36 | {1'b0, b[7:1]} + {2'b00, b[7:2]}}; 37 | 38 | 2: // reduce 50% = 1/2 39 | dout = {{1'b0, r[7:1]}, 40 | {1'b0, g[7:1]}, 41 | {1'b0, b[7:1]}}; 42 | 43 | 3: // reduce 75% = 1/4 44 | dout = {{2'b00, r[7:2]}, 45 | {2'b00, g[7:2]}, 46 | {2'b00, b[7:2]}}; 47 | 48 | default: dout = {r,g,b}; 49 | endcase 50 | end 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /releases/Dig Dug.mra: -------------------------------------------------------------------------------- 1 | 2 | Dig Dug (rev 2) 3 | 0220 4 | digdug 5 | 20200427161917 6 | 1982 7 | Namco 8 | Maze / Digging 9 | digdug 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Arcade-DigDug.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2017 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel FPGA IP License Agreement, or other applicable license 12 | # agreement, including, without limitation, that your use is for 13 | # the sole purpose of programming logic devices manufactured by 14 | # Intel and sold by Intel or its authorized distributors. Please 15 | # refer to the applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus Prime 20 | # Version 17.1.0 Build 590 10/25/2017 SJ Lite Edition 21 | # Date created = 11:35:41 April 26, 2019 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "17.1" 26 | DATE = "11:35:41 April 26, 2019" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "Arcade-DigDug" 31 | -------------------------------------------------------------------------------- /sys/i2c.v: -------------------------------------------------------------------------------- 1 | 2 | module i2c 3 | ( 4 | input CLK, 5 | 6 | input START, 7 | input [23:0] I2C_DATA, 8 | output reg END = 1, 9 | output reg ACK = 0, 10 | 11 | //I2C bus 12 | output I2C_SCL, 13 | inout I2C_SDA 14 | ); 15 | 16 | 17 | // Clock Setting 18 | parameter CLK_Freq = 50_000_000; // 50 MHz 19 | parameter I2C_Freq = 400_000; // 400 KHz 20 | 21 | reg I2C_CLOCK; 22 | always@(negedge CLK) begin 23 | integer mI2C_CLK_DIV = 0; 24 | if(mI2C_CLK_DIV < (CLK_Freq/I2C_Freq)) begin 25 | mI2C_CLK_DIV <= mI2C_CLK_DIV + 1; 26 | end else begin 27 | mI2C_CLK_DIV <= 0; 28 | I2C_CLOCK <= ~I2C_CLOCK; 29 | end 30 | end 31 | 32 | assign I2C_SCL = SCLK | I2C_CLOCK; 33 | assign I2C_SDA = SDO ? 1'bz : 1'b0; 34 | 35 | reg SCLK = 1, SDO = 1; 36 | 37 | always @(posedge CLK) begin 38 | reg old_clk; 39 | reg old_st; 40 | 41 | reg [5:0] SD_COUNTER = 'b111111; 42 | reg [0:31] SD; 43 | 44 | old_clk <= I2C_CLOCK; 45 | old_st <= START; 46 | 47 | if(~old_st && START) begin 48 | SCLK <= 1; 49 | SDO <= 1; 50 | ACK <= 0; 51 | END <= 0; 52 | SD <= {2'b10, I2C_DATA[23:16], 1'b1, I2C_DATA[15:8], 1'b1, I2C_DATA[7:0], 4'b1011}; 53 | SD_COUNTER <= 0; 54 | end else begin 55 | if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin 56 | SD_COUNTER <= SD_COUNTER + 6'd1; 57 | case(SD_COUNTER) 58 | 01: SCLK <= 0; 59 | 10,19,28: ACK <= ACK | I2C_SDA; 60 | 29: SCLK <= 1; 61 | 32: END <= 1; 62 | endcase 63 | end 64 | 65 | if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO <= SD[SD_COUNTER[4:0]]; 66 | end 67 | end 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /src/cpucore.v: -------------------------------------------------------------------------------- 1 | module CPUCORE 2 | ( 3 | input RESET, 4 | input CLK, 5 | input IRQ, 6 | input NMI, 7 | output RD, 8 | output WR, 9 | output [15:0] AD, 10 | input DV, 11 | input [7:0] DI, 12 | input [7:0] IR, 13 | output [7:0] DO 14 | ); 15 | 16 | wire [7:0] m_do; 17 | wire [15:0] m_ad; 18 | wire m_irq, m_nmi, m_me, m_ie, m_rd, m_wr; 19 | 20 | wire m_mx = (~m_me); 21 | wire m_mr = (~m_rd) & m_mx; 22 | wire m_mw = (~m_wr) & m_mx; 23 | 24 | wire cs_mrom = ( m_ad[15:14] == 2'b00 ); 25 | wire cs_nodv = cs_mrom; 26 | 27 | wire [7:0] m_di = cs_mrom ? IR : DV ? DI : 8'hFF; 28 | 29 | assign m_irq = ~IRQ; 30 | assign m_nmi = ~NMI; 31 | 32 | tv80s core( 33 | .mreq_n(m_me), 34 | .iorq_n(m_ie), 35 | .rd_n(m_rd), 36 | .wr_n(m_wr), 37 | .A(m_ad), 38 | .do(m_do), 39 | 40 | .reset_n(~RESET), 41 | .clk(CLK), 42 | .wait_n(1'b1), 43 | .int_n(m_irq), 44 | .nmi_n(m_nmi), 45 | .busrq_n(1'b1), 46 | .di(m_di) 47 | ); 48 | 49 | assign RD = m_mr & ~cs_nodv; 50 | assign WR = m_mw & ~cs_nodv; 51 | assign AD = m_ad; 52 | assign DO = m_do; 53 | 54 | endmodule 55 | 56 | 57 | //----------------------------------------------- 58 | // NMI Ack Control 59 | //----------------------------------------------- 60 | module CPUNMIACK 61 | ( 62 | input RST, 63 | input CL, 64 | input [15:0] AD, 65 | input NMI, 66 | output reg NMIo 67 | ); 68 | 69 | reg pNMI = 1'b0; 70 | wire NMIACK = ( AD == 16'h0066 ); 71 | always @( negedge CL or posedge RST ) begin 72 | if (RST) begin 73 | pNMI <= 1'b0; 74 | NMIo <= 1'b0; 75 | end 76 | else begin 77 | if (NMIACK) NMIo <= 0; 78 | else if ((pNMI^NMI) & NMI) NMIo <= 1'b1; 79 | pNMI <= NMI; 80 | end 81 | end 82 | 83 | endmodule 84 | 85 | -------------------------------------------------------------------------------- /sys/sys_top.sdc: -------------------------------------------------------------------------------- 1 | # Specify root clocks 2 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] 3 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] 4 | create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] 5 | create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] 6 | create_clock -period 10.0 [get_pins -compatibility_mode spi|sclk_out] -name spi_sck 7 | 8 | derive_pll_clocks 9 | 10 | # Specify PLL-generated clock(s) 11 | create_generated_clock -source [get_pins -compatibility_mode {pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}] \ 12 | -name HDMI_CLK [get_ports HDMI_TX_CLK] 13 | 14 | derive_clock_uncertainty 15 | 16 | # Decouple different clock groups (to simplify routing) 17 | set_clock_groups -asynchronous \ 18 | -group [get_clocks { *|pll|pll_inst|altera_pll_i|general[*].gpll~PLL_OUTPUT_COUNTER|divclk}] \ 19 | -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk}] \ 20 | -group [get_clocks { *|h2f_user0_clk}] \ 21 | -group [get_clocks { FPGA_CLK1_50 FPGA_CLK2_50 FPGA_CLK3_50}] 22 | 23 | set_output_delay -max -clock HDMI_CLK 2.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] 24 | set_output_delay -min -clock HDMI_CLK -1.5ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] 25 | 26 | set_false_path -from {*} -to [get_registers {wcalc[*] hcalc[*]}] 27 | 28 | 29 | # Put constraints on input ports 30 | set_false_path -from [get_ports {KEY*}] -to * 31 | set_false_path -from [get_ports {BTN_*}] -to * 32 | 33 | # Put constraints on output ports 34 | set_false_path -from * -to [get_ports {LED_*}] 35 | set_false_path -from * -to [get_ports {VGA_*}] 36 | set_false_path -from * -to [get_ports {AUDIO_SPDIF}] 37 | set_false_path -from * -to [get_ports {AUDIO_L}] 38 | set_false_path -from * -to [get_ports {AUDIO_R}] 39 | -------------------------------------------------------------------------------- /sys/video_cleaner.sv: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2018 Sorgelig 4 | // 5 | // This program is GPL Licensed. See COPYING for the full license. 6 | // 7 | // 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | `timescale 1ns / 1ps 11 | 12 | module video_cleaner 13 | ( 14 | input clk_vid, 15 | input ce_pix, 16 | 17 | input [7:0] R, 18 | input [7:0] G, 19 | input [7:0] B, 20 | 21 | input HSync, 22 | input VSync, 23 | input HBlank, 24 | input VBlank, 25 | 26 | // video output signals 27 | output reg [7:0] VGA_R, 28 | output reg [7:0] VGA_G, 29 | output reg [7:0] VGA_B, 30 | output reg VGA_VS, 31 | output reg VGA_HS, 32 | output VGA_DE, 33 | 34 | // optional aligned blank 35 | output reg HBlank_out, 36 | output reg VBlank_out 37 | ); 38 | 39 | wire hs, vs; 40 | s_fix sync_v(clk_vid, HSync, hs); 41 | s_fix sync_h(clk_vid, VSync, vs); 42 | 43 | wire hbl = hs | HBlank; 44 | wire vbl = vs | VBlank; 45 | 46 | assign VGA_DE = ~(HBlank_out | VBlank_out); 47 | 48 | always @(posedge clk_vid) begin 49 | if(ce_pix) begin 50 | HBlank_out <= hbl; 51 | 52 | VGA_VS <= vs; 53 | VGA_HS <= hs; 54 | VGA_R <= R; 55 | VGA_G <= G; 56 | VGA_B <= B; 57 | 58 | if(HBlank_out & ~hbl) VBlank_out <= vbl; 59 | end 60 | end 61 | 62 | endmodule 63 | 64 | module s_fix 65 | ( 66 | input clk, 67 | 68 | input sync_in, 69 | output sync_out 70 | ); 71 | 72 | assign sync_out = sync_in ^ pol; 73 | 74 | reg pol; 75 | always @(posedge clk) begin 76 | integer pos = 0, neg = 0, cnt = 0; 77 | reg s1,s2; 78 | 79 | s1 <= sync_in; 80 | s2 <= s1; 81 | 82 | if(~s2 & s1) neg <= cnt; 83 | if(s2 & ~s1) pos <= cnt; 84 | 85 | cnt <= cnt + 1; 86 | if(s2 != s1) cnt <= 0; 87 | 88 | pol <= pos > neg; 89 | end 90 | 91 | endmodule 92 | -------------------------------------------------------------------------------- /sys/sys.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] 2 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] 3 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.qip ] 4 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] 5 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.qip ] 6 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] 7 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] 8 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] 9 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] 10 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] 11 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] 12 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] 13 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] 14 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] 15 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] 16 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] 17 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] 18 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] 19 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] 20 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] 21 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] 22 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] 23 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ] 24 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] 25 | set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi 26 | -------------------------------------------------------------------------------- /sys/build_id.tcl: -------------------------------------------------------------------------------- 1 | 2 | # Build TimeStamp Verilog Module 3 | # Jeff Wiencrot - 8/1/2011 4 | proc generateBuildID_Verilog {} { 5 | 6 | # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) 7 | set buildDate [ clock format [ clock seconds ] -format %y%m%d ] 8 | set buildTime [ clock format [ clock seconds ] -format %H%M%S ] 9 | 10 | # Create a Verilog file for output 11 | set outputFileName "build_id.v" 12 | set outputFile [open $outputFileName "w"] 13 | 14 | # Output the Verilog source 15 | puts $outputFile "`define BUILD_DATE \"$buildDate\"" 16 | puts $outputFile "`define BUILD_TIME \"$buildTime\"" 17 | close $outputFile 18 | 19 | # Send confirmation message to the Messages window 20 | post_message "Generated build identification Verilog module: [pwd]/$outputFileName" 21 | post_message "Date: $buildDate" 22 | post_message "Time: $buildTime" 23 | } 24 | 25 | # Build CDF file 26 | # Sorgelig - 17/2/2018 27 | proc generateCDF {revision device outpath} { 28 | 29 | set outputFileName "jtag.cdf" 30 | set outputFile [open $outputFileName "w"] 31 | 32 | puts $outputFile "JedecChain;" 33 | puts $outputFile " FileRevision(JESD32A);" 34 | puts $outputFile " DefaultMfr(6E);" 35 | puts $outputFile "" 36 | puts $outputFile " P ActionCode(Ign)" 37 | puts $outputFile " Device PartName(SOCVHPS) MfrSpec(OpMask(0));" 38 | puts $outputFile " P ActionCode(Cfg)" 39 | puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" 40 | puts $outputFile "ChainEnd;" 41 | puts $outputFile "" 42 | puts $outputFile "AlteraBegin;" 43 | puts $outputFile " ChainType(JTAG);" 44 | puts $outputFile "AlteraEnd;" 45 | } 46 | 47 | set project_name [lindex $quartus(args) 1] 48 | set revision [lindex $quartus(args) 2] 49 | 50 | if {[project_exists $project_name]} { 51 | if {[string equal "" $revision]} { 52 | project_open $project_name -revision [get_current_revision $project_name] 53 | } else { 54 | project_open $project_name -revision $revision 55 | } 56 | } else { 57 | post_message -type error "Project $project_name does not exist" 58 | exit 59 | } 60 | 61 | set device [get_global_assignment -name DEVICE] 62 | set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] 63 | 64 | if [is_project_open] { 65 | project_close 66 | } 67 | 68 | generateBuildID_Verilog 69 | generateCDF $revision $device $outpath 70 | -------------------------------------------------------------------------------- /sys/pll/pll_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module pll_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'outclk1' 14 | output wire outclk_1, 15 | 16 | // interface 'locked' 17 | output wire locked 18 | ); 19 | 20 | altera_pll #( 21 | .fractional_vco_multiplier("false"), 22 | .reference_clock_frequency("50.0 MHz"), 23 | .operation_mode("direct"), 24 | .number_of_clocks(2), 25 | .output_clock_frequency0("49.147727 MHz"), 26 | .phase_shift0("0 ps"), 27 | .duty_cycle0(50), 28 | .output_clock_frequency1("24.573863 MHz"), 29 | .phase_shift1("0 ps"), 30 | .duty_cycle1(50), 31 | .output_clock_frequency2("0 MHz"), 32 | .phase_shift2("0 ps"), 33 | .duty_cycle2(50), 34 | .output_clock_frequency3("0 MHz"), 35 | .phase_shift3("0 ps"), 36 | .duty_cycle3(50), 37 | .output_clock_frequency4("0 MHz"), 38 | .phase_shift4("0 ps"), 39 | .duty_cycle4(50), 40 | .output_clock_frequency5("0 MHz"), 41 | .phase_shift5("0 ps"), 42 | .duty_cycle5(50), 43 | .output_clock_frequency6("0 MHz"), 44 | .phase_shift6("0 ps"), 45 | .duty_cycle6(50), 46 | .output_clock_frequency7("0 MHz"), 47 | .phase_shift7("0 ps"), 48 | .duty_cycle7(50), 49 | .output_clock_frequency8("0 MHz"), 50 | .phase_shift8("0 ps"), 51 | .duty_cycle8(50), 52 | .output_clock_frequency9("0 MHz"), 53 | .phase_shift9("0 ps"), 54 | .duty_cycle9(50), 55 | .output_clock_frequency10("0 MHz"), 56 | .phase_shift10("0 ps"), 57 | .duty_cycle10(50), 58 | .output_clock_frequency11("0 MHz"), 59 | .phase_shift11("0 ps"), 60 | .duty_cycle11(50), 61 | .output_clock_frequency12("0 MHz"), 62 | .phase_shift12("0 ps"), 63 | .duty_cycle12(50), 64 | .output_clock_frequency13("0 MHz"), 65 | .phase_shift13("0 ps"), 66 | .duty_cycle13(50), 67 | .output_clock_frequency14("0 MHz"), 68 | .phase_shift14("0 ps"), 69 | .duty_cycle14(50), 70 | .output_clock_frequency15("0 MHz"), 71 | .phase_shift15("0 ps"), 72 | .duty_cycle15(50), 73 | .output_clock_frequency16("0 MHz"), 74 | .phase_shift16("0 ps"), 75 | .duty_cycle16(50), 76 | .output_clock_frequency17("0 MHz"), 77 | .phase_shift17("0 ps"), 78 | .duty_cycle17(50), 79 | .pll_type("General"), 80 | .pll_subtype("General") 81 | ) altera_pll_i ( 82 | .rst (rst), 83 | .outclk ({outclk_1, outclk_0}), 84 | .locked (locked), 85 | .fboutclk ( ), 86 | .fbclk (1'b0), 87 | .refclk (refclk) 88 | ); 89 | endmodule 90 | 91 | -------------------------------------------------------------------------------- /src/dprams.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // Dualport RAM modules for FPGA DigDug 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module DPR2KV 7 | ( 8 | input CL0, 9 | input [10:0] AD0, 10 | input EN0, 11 | input WR0, 12 | input [7:0] DI0, 13 | output [7:0] DO0, 14 | 15 | input CL1, 16 | input [10:0] AD1, 17 | output [7:0] DO1 18 | ); 19 | 20 | DPR2K ram( 21 | CL0, AD0, EN0, WR0, DI0, DO0, 22 | CL1, AD1, 1'b1, 1'b0, 8'h0, DO1 23 | ); 24 | 25 | endmodule 26 | 27 | 28 | module DPR2K 29 | ( 30 | input CL0, 31 | input [10:0] AD0, 32 | input EN0, 33 | input WR0, 34 | input [7:0] DI0, 35 | output reg [7:0] DO0, 36 | 37 | input CL1, 38 | input [10:0] AD1, 39 | input EN1, 40 | input WR1, 41 | input [7:0] DI1, 42 | output reg [7:0] DO1 43 | ); 44 | 45 | reg [7:0] core[0:2047]; 46 | 47 | always @( posedge CL0 ) begin 48 | if (EN0) begin 49 | DO0 <= core[AD0]; 50 | if (WR0) core[AD0] <= DI0; 51 | end 52 | end 53 | 54 | always @( posedge CL1 ) begin 55 | if (EN1) begin 56 | DO1 <= core[AD1]; 57 | if (WR1) core[AD1] <= DI1; 58 | end 59 | end 60 | 61 | endmodule 62 | 63 | 64 | module LBUF1K 65 | ( 66 | input CL0, 67 | input [9:0] AD0, 68 | input WR0, 69 | input [7:0] DI0, 70 | 71 | input CL1, 72 | input [9:0] AD1, 73 | input WR1, 74 | input [7:0] DI1, 75 | output [7:0] DO1 76 | ); 77 | 78 | wire [7:0] non; 79 | 80 | LINEBUF lbuf( 81 | AD0,AD1, 82 | CL0,CL1, 83 | DI0,DI1, 84 | WR0,WR1, 85 | non,DO1 86 | ); 87 | 88 | endmodule 89 | 90 | 91 | module DLROM #(parameter AW,parameter DW) 92 | ( 93 | input CL0, 94 | input [(AW-1):0] AD0, 95 | output reg [(DW-1):0] DO0, 96 | 97 | input CL1, 98 | input [(AW-1):0] AD1, 99 | input [(DW-1):0] DI1, 100 | input WE1 101 | ); 102 | 103 | reg [DW:0] core[0:((2**AW)-1)]; 104 | 105 | always @(posedge CL0) DO0 <= core[AD0]; 106 | always @(posedge CL1) if (WE1) core[AD1] <= DI1; 107 | 108 | endmodule 109 | 110 | 111 | module DLROMe #(parameter AW,parameter DW) 112 | ( 113 | input RE0, 114 | input CL0, 115 | input [(AW-1):0] AD0, 116 | output reg [(DW-1):0] DO0, 117 | 118 | input CL1, 119 | input [(AW-1):0] AD1, 120 | input [(DW-1):0] DI1, 121 | input WE1 122 | ); 123 | 124 | reg [DW:0] core[0:((2**AW)-1)]; 125 | 126 | always @(posedge CL0) if (RE0) DO0 <= core[AD0]; 127 | always @(posedge CL1) if (WE1) core[AD1] <= DI1; 128 | 129 | endmodule 130 | 131 | -------------------------------------------------------------------------------- /src/cpu/tv80_reg.v: -------------------------------------------------------------------------------- 1 | // 2 | // TV80 8-Bit Microprocessor Core 3 | // Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) 4 | // 5 | // Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a 8 | // copy of this software and associated documentation files (the "Software"), 9 | // to deal in the Software without restriction, including without limitation 10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | // and/or sell copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | module tv80_reg (/*AUTOARG*/ 26 | // Outputs 27 | DOBH, DOAL, DOCL, DOBL, DOCH, DOAH, 28 | // Inputs 29 | AddrC, AddrA, AddrB, DIH, DIL, clk, CEN, WEH, WEL 30 | ); 31 | input [2:0] AddrC; 32 | output [7:0] DOBH; 33 | input [2:0] AddrA; 34 | input [2:0] AddrB; 35 | input [7:0] DIH; 36 | output [7:0] DOAL; 37 | output [7:0] DOCL; 38 | input [7:0] DIL; 39 | output [7:0] DOBL; 40 | output [7:0] DOCH; 41 | output [7:0] DOAH; 42 | input clk, CEN, WEH, WEL; 43 | 44 | reg [7:0] RegsH [0:7]; 45 | reg [7:0] RegsL [0:7]; 46 | 47 | always @(posedge clk) 48 | begin 49 | if (CEN) 50 | begin 51 | if (WEH) RegsH[AddrA] <= DIH; 52 | if (WEL) RegsL[AddrA] <= DIL; 53 | end 54 | end 55 | 56 | assign DOAH = RegsH[AddrA]; 57 | assign DOAL = RegsL[AddrA]; 58 | assign DOBH = RegsH[AddrB]; 59 | assign DOBL = RegsL[AddrB]; 60 | assign DOCH = RegsH[AddrC]; 61 | assign DOCL = RegsL[AddrC]; 62 | 63 | // break out ram bits for waveform debug 64 | wire [7:0] H = RegsH[2]; 65 | wire [7:0] L = RegsL[2]; 66 | 67 | // synopsys dc_script_begin 68 | // set_attribute current_design "revision" "$Id: tv80_reg.v,v 1.1 2004/05/16 17:39:57 ghutchis Exp $" -type string -quiet 69 | // synopsys dc_script_end 70 | endmodule 71 | 72 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------- 2 | -- 3 | -- Arcade: DigDug port to MiSTer by MiSTer-X 4 | -- 21 September 2019 5 | -- 6 | --------------------------------------------------------------------------------- 7 | -- FPGA DigDug for XILINX Spartan-6 8 | ------------------------------------------------ 9 | -- Copyright (c) 2017 MiSTer-X 10 | --------------------------------------------------------------------------------- 11 | -- T80/T80s - Version : 0242 12 | ----------------------------- 13 | -- TV80 8-Bit Microprocessor Core 14 | -- Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) 15 | -- 16 | -- Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) 17 | --------------------------------------------------------------------------------- 18 | -- 19 | -- 20 | -- Keyboard inputs : 21 | -- 22 | -- F2 : Coin + Start 2 players 23 | -- F1 : Coin + Start 1 player 24 | -- UP,DOWN,LEFT,RIGHT arrows : Movements 25 | -- SPACE/CTRL : Pump 26 | -- 27 | -- MAME/IPAC/JPAC Style Keyboard inputs: 28 | -- 5 : Coin 1 29 | -- 6 : Coin 2 30 | -- 1 : Start 1 Player 31 | -- 2 : Start 2 Players 32 | -- R,F,D,G : Player 2 Movements 33 | -- A/S : Player 2 Pump 34 | -- 35 | -- 36 | -- Joystick support. 37 | -- 38 | -- 39 | --------------------------------------------------------------------------------- 40 | -- 21 September 2019 41 | --------------------------------------------------------------------------------- 42 | -- FIXED: wrong aspect ratio in "Vert" mode. 43 | --------------------------------------------------------------------------------- 44 | -- 22 October 2019 45 | --------------------------------------------------------------------------------- 46 | -- FIXED: Little problem with CRT and HDMI. 47 | -- CHANGED: Keyboard inputs. 48 | -- Abolished rotation of control direction in Horz mode. 49 | --------------------------------------------------------------------------------- 50 | 51 | *** Attention *** 52 | 53 | ROMs are not included. In order to use this arcade, you need to provide the 54 | correct ROMs. 55 | 56 | To simplify the process .mra files are provided in the releases folder, that 57 | specifies the required ROMs with checksums. The ROMs .zip filename refers to the 58 | corresponding file of the M.A.M.E. project. 59 | 60 | Please refer to https://github.com/MiSTer-devel/Main_MiSTer/wiki/Arcade-Roms for 61 | information on how to setup and use the environment. 62 | 63 | Quickreference for folders and file placement: 64 | 65 | /_Arcade/.mra 66 | /_Arcade/cores/.rbf 67 | /_Arcade/mame/.zip 68 | /_Arcade/hbmame/.zip 69 | 70 | -------------------------------------------------------------------------------- /sys/sys_q13.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] 2 | set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] 3 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll.v ] 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll/pll_0002.v ] 5 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll/pll_0002.qip ] 6 | set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_q13.qip ] 7 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.v ] 8 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_core.v ] 9 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_top.v ] 10 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] 11 | set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] 12 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] 13 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] 14 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] 15 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] 16 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] 17 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] 18 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] 19 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] 20 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] 21 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] 22 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] 23 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] 24 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] 25 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] 26 | set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] 27 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ] 28 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] 29 | set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi 30 | -------------------------------------------------------------------------------- /sys/i2s.v: -------------------------------------------------------------------------------- 1 | 2 | module i2s 3 | #( 4 | parameter CLK_RATE = 50000000, 5 | parameter AUDIO_DW = 16, 6 | parameter AUDIO_RATE = 96000 7 | ) 8 | ( 9 | input reset, 10 | input clk_sys, 11 | input half_rate, 12 | 13 | output reg sclk, 14 | output reg lrclk, 15 | output reg sdata, 16 | 17 | input [AUDIO_DW-1:0] left_chan, 18 | input [AUDIO_DW-1:0] right_chan 19 | ); 20 | 21 | localparam WHOLE_CYCLES = (CLK_RATE) / (AUDIO_RATE*AUDIO_DW*4); 22 | localparam ERROR_BASE = 10000; 23 | localparam [63:0] ERRORS_PER_BIT = ((CLK_RATE * ERROR_BASE) / (AUDIO_RATE*AUDIO_DW*4)) - (WHOLE_CYCLES * ERROR_BASE); 24 | 25 | reg lpf_ce; 26 | wire [AUDIO_DW-1:0] al, ar; 27 | 28 | lpf_i2s lpf_l 29 | ( 30 | .CLK(clk_sys), 31 | .CE(lpf_ce), 32 | .IDATA(left_chan), 33 | .ODATA(al) 34 | ); 35 | 36 | lpf_i2s lpf_r 37 | ( 38 | .CLK(clk_sys), 39 | .CE(lpf_ce), 40 | 41 | .IDATA(right_chan), 42 | .ODATA(ar) 43 | ); 44 | 45 | always @(posedge clk_sys) begin 46 | reg [31:0] count_q; 47 | reg [31:0] error_q; 48 | reg [7:0] bit_cnt; 49 | reg skip = 0; 50 | 51 | reg [AUDIO_DW-1:0] left; 52 | reg [AUDIO_DW-1:0] right; 53 | 54 | reg msclk; 55 | reg ce; 56 | 57 | lpf_ce <= 0; 58 | 59 | if (reset) begin 60 | count_q <= 0; 61 | error_q <= 0; 62 | ce <= 0; 63 | bit_cnt <= 1; 64 | lrclk <= 1; 65 | sclk <= 1; 66 | msclk <= 1; 67 | end 68 | else 69 | begin 70 | if(count_q == WHOLE_CYCLES-1) begin 71 | if (error_q < (ERROR_BASE - ERRORS_PER_BIT)) begin 72 | error_q <= error_q + ERRORS_PER_BIT[31:0]; 73 | count_q <= 0; 74 | end else begin 75 | error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE; 76 | count_q <= count_q + 1; 77 | end 78 | end else if(count_q == WHOLE_CYCLES) begin 79 | count_q <= 0; 80 | end else begin 81 | count_q <= count_q + 1; 82 | end 83 | 84 | sclk <= msclk; 85 | if(!count_q) begin 86 | ce <= ~ce; 87 | if(~half_rate || ce) begin 88 | msclk <= ~msclk; 89 | if(msclk) begin 90 | skip <= ~skip; 91 | if(skip) lpf_ce <= 1; 92 | if(bit_cnt >= AUDIO_DW) begin 93 | bit_cnt <= 1; 94 | lrclk <= ~lrclk; 95 | if(lrclk) begin 96 | left <= al; 97 | right <= ar; 98 | end 99 | end 100 | else begin 101 | bit_cnt <= bit_cnt + 1'd1; 102 | end 103 | sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt]; 104 | end 105 | end 106 | end 107 | end 108 | end 109 | 110 | endmodule 111 | 112 | module lpf_i2s 113 | ( 114 | input CLK, 115 | input CE, 116 | input [15:0] IDATA, 117 | output reg [15:0] ODATA 118 | ); 119 | 120 | reg [511:0] acc; 121 | reg [20:0] sum; 122 | 123 | always @(*) begin 124 | integer i; 125 | sum = 0; 126 | for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]}; 127 | end 128 | 129 | always @(posedge CLK) begin 130 | if(CE) begin 131 | acc <= {acc[495:0], IDATA}; 132 | ODATA <= sum[20:5]; 133 | end 134 | end 135 | 136 | endmodule 137 | -------------------------------------------------------------------------------- /sys/vga_out.sv: -------------------------------------------------------------------------------- 1 | 2 | module vga_out 3 | ( 4 | input ypbpr_full, 5 | input ypbpr_en, 6 | 7 | input [23:0] din, 8 | output [23:0] dout 9 | ); 10 | 11 | wire [5:0] yuv_full[225] = '{ 12 | 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, 13 | 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, 14 | 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, 15 | 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, 16 | 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, 17 | 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, 18 | 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, 19 | 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, 20 | 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, 21 | 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, 22 | 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, 23 | 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, 24 | 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, 25 | 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, 26 | 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, 27 | 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, 28 | 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, 29 | 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, 30 | 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, 31 | 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, 32 | 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, 33 | 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, 34 | 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, 35 | 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, 36 | 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, 37 | 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, 38 | 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, 39 | 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, 40 | 6'd63 41 | }; 42 | 43 | wire [5:0] red = din[23:18]; 44 | wire [5:0] green = din[15:10]; 45 | wire [5:0] blue = din[7:2]; 46 | 47 | // http://marsee101.blog19.fc2.com/blog-entry-2311.html 48 | // Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) 49 | // Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) 50 | // Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) 51 | 52 | wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); 53 | wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); 54 | wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); 55 | 56 | wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; 57 | wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; 58 | wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; 59 | 60 | assign dout[23:16] = ypbpr_en ? {(ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]), 2'b00} : din[23:16]; 61 | assign dout[15:8] = ypbpr_en ? {(ypbpr_full ? yuv_full[y -8'd16] : y[7:2]), 2'b00} : din[15:8]; 62 | assign dout[7:0] = ypbpr_en ? {(ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]), 2'b00} : din[7:0]; 63 | 64 | 65 | endmodule 66 | -------------------------------------------------------------------------------- /src/DIGDUG_SPRITE.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // FPGA DigDug (Sprite part) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module DIGDUG_SPRITE 7 | ( 8 | input RCLK, // Rendering Clock 9 | input VCLK, // Video Dot Clock 10 | input VCLKx2, // Video Dot Clockx2 11 | 12 | input [8:0] POSH, 13 | input [8:0] POSV, 14 | 15 | output SPATCL, 16 | output [6:0] SPATAD, 17 | input [23:0] SPATDT, 18 | 19 | output reg [4:0] SPCOL, 20 | 21 | 22 | input ROMCL, // Downloaded ROM image 23 | input [15:0] ROMAD, 24 | input [7:0] ROMDT, 25 | input ROMEN 26 | ); 27 | 28 | wire [8:0] PH = POSH+1; 29 | wire [8:0] PV = POSV+2; 30 | wire [8:0] TY; 31 | 32 | 33 | reg [3:0] PHASE; 34 | reg SIDE; 35 | 36 | reg [7:0] ADR; 37 | reg [23:0] ATR0, ATR1; 38 | 39 | reg [8:0] WXP; 40 | reg [8:0] WCN; 41 | 42 | 43 | wire SZ = ATR0[7]; // Size 44 | wire [8:0] SS = SZ ? 32 : 16; // Size (Pixels) 45 | wire [5:0] SC = ATR1[5:0]; // Color 46 | wire [8:0] SX = {1'b0,ATR1[15:8]}-9'd39; // Position X 47 | wire [8:0] SY = (9'd256-TY); // Position Y 48 | wire [8:0] SU = (SS-WCN)^{9{ATR0[16]}}; // Position U 49 | wire [8:0] SV = (PV-SY )^{9{ATR0[17]}}; // Position V 50 | wire [7:0] SM = ATR0[7:0]; // Code (for Normal) 51 | wire [7:0] SL = {SM[7]|SM[5],SM[6]|SM[4],SM[3:0],SV[4],SU[4]}; // Code (for Size) 52 | wire [7:0] SN = SZ ? SL : SM; // Code 53 | wire SD = ATR1[17]|((PV=(SY+SS)); // Visiblity (False:Visible) 54 | 55 | assign TY = ((({1'b0,ATR0[15:8]}+1)+(SZ ? 9'd16 : 9'd0)) & 9'd255) + 9'd30; 56 | 57 | wire ABORT = (PH==288); 58 | wire STANDBY = (PH!=289); 59 | wire ATRTAIL = (ADR[7]); 60 | wire DRAWING = (WCN!=1); 61 | 62 | 63 | assign SPATCL = ~RCLK; 64 | assign SPATAD = ADR[6:0]; 65 | 66 | wire [8:0] WSX = {1'b0,SX[7:0]} + ((SX[7:0]<8'd16) ? 9'd256 : 9'd0); 67 | 68 | always @( posedge RCLK ) begin 69 | if (ABORT) begin PHASE <= 0; WCN <= 0; end 70 | else case (PHASE) 71 | `define LOOP (PHASE) 72 | `define NEXT (PHASE+1) 73 | `define NXTA (1) 74 | 0: begin SIDE <= PV[0]; ADR <= 0; WCN <= 0; PHASE <= STANDBY ? `LOOP : `NEXT; end 75 | 1: begin PHASE <= ATRTAIL ? `NXTA : `NEXT; end 76 | 2: begin ATR0 <= SPATDT; ADR <= ADR+1; PHASE <= `NEXT; end 77 | 3: begin ATR1 <= SPATDT; ADR <= ADR+1; PHASE <= `NEXT; end 78 | 4: begin WXP <= WSX; WCN <= SS; PHASE <= SD ? `NXTA : `NEXT; end 79 | // CHIP Read 80 | 5: begin /* CLUT Read */ PHASE <= `NEXT; end 81 | // LBUF Write 82 | 6: begin WXP <= WXP+1; WCN <= WCN-1; PHASE <= DRAWING ? 5 : `NXTA; end 83 | default:; 84 | endcase 85 | end 86 | 87 | wire [7:0] CHRD; 88 | DLROMe #(14,8) spchip((PHASE==5),~RCLK,{SN,SV[3],SU[3:2],SV[2:0]},CHRD, ROMCL,ROMAD[14:0],ROMDT,ROMEN & (ROMAD[15:14]==2'b01)); 89 | wire [7:0] PIX = CHRD << (SU[1:0]); 90 | 91 | wire [7:0] WDT; 92 | DLROMe #(8,8) spclut((PHASE==5), RCLK,{SC,PIX[7],PIX[3]},WDT, ROMCL,ROMAD[7:0],ROMDT,ROMEN & (ROMAD[15:8]==8'hD9)); 93 | 94 | wire [4:0] LBOUT; 95 | LBUF1K lbuf ( 96 | ~RCLK, {SIDE,WXP}, (PHASE==6) & (PIX[7]|PIX[3]), {4'h1,WDT[3:0]}, 97 | VCLKx2, {~SIDE,PH}, (radr0==radr1), 8'h0, LBOUT 98 | ); 99 | 100 | reg [9:0] radr0=0,radr1=1; 101 | always @(posedge VCLK) radr0 <= {~SIDE,PH}; 102 | always @(negedge VCLK) begin 103 | if (radr0!=radr1) SPCOL <= LBOUT; 104 | radr1 <= radr0; 105 | end 106 | 107 | endmodule 108 | 109 | -------------------------------------------------------------------------------- /sys/alsa.sv: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // 3 | // ALSA sound support for MiSTer 4 | // (c)2019 Sorgelig 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or (at your option) 9 | // any later version. 10 | // 11 | // This program is distributed in the hope that it will be useful, but WITHOUT 12 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | // more details. 15 | // 16 | // You should have received a copy of the GNU General Public License along 17 | // with this program; if not, write to the Free Software Foundation, Inc., 18 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | // 20 | //============================================================================ 21 | 22 | module alsa 23 | ( 24 | input reset, 25 | 26 | input ram_clk, 27 | output reg [28:0] ram_address, 28 | output reg [7:0] ram_burstcount, 29 | input ram_waitrequest, 30 | input [63:0] ram_readdata, 31 | input ram_readdatavalid, 32 | output reg ram_read, 33 | 34 | input spi_ss, 35 | input spi_sck, 36 | input spi_mosi, 37 | 38 | output reg [15:0] pcm_l, 39 | output reg [15:0] pcm_r 40 | ); 41 | 42 | reg spi_new = 0; 43 | reg [127:0] spi_data; 44 | always @(posedge spi_sck, posedge spi_ss) begin 45 | reg [7:0] mosi; 46 | reg [6:0] spicnt = 0; 47 | 48 | if(spi_ss) spicnt <= 0; 49 | else begin 50 | mosi <= {mosi[6:0],spi_mosi}; 51 | 52 | spicnt <= spicnt + 1'd1; 53 | if(&spicnt[2:0]) begin 54 | spi_data[{spicnt[6:3],3'b000} +:8] <= {mosi[6:0],spi_mosi}; 55 | spi_new <= &spicnt; 56 | end 57 | end 58 | end 59 | 60 | reg [31:0] buf_addr; 61 | reg [31:0] buf_len; 62 | reg [31:0] buf_wptr = 0; 63 | 64 | always @(posedge ram_clk) begin 65 | reg n1,n2,n3; 66 | reg [127:0] data1,data2; 67 | 68 | n1 <= spi_new; 69 | n2 <= n1; 70 | n3 <= n2; 71 | 72 | data1 <= spi_data; 73 | data2 <= data1; 74 | 75 | if(~n3 & n2) {buf_wptr,buf_len,buf_addr} <= data2[95:0]; 76 | end 77 | 78 | reg [31:0] buf_rptr = 0; 79 | always @(posedge ram_clk) begin 80 | reg got_first = 0; 81 | reg ready = 0; 82 | reg ud; 83 | reg [31:0] readdata; 84 | 85 | if(~ram_waitrequest) ram_read <= 0; 86 | if(ram_readdatavalid && ram_burstcount) begin 87 | ram_burstcount <= 0; 88 | ready <= 1; 89 | readdata <= ud ? ram_readdata[63:32] : ram_readdata[31:0]; 90 | if(buf_rptr[31:2] >= buf_len[31:2]) buf_rptr <= 0; 91 | end 92 | 93 | if(reset) {ready, got_first} <= 0; 94 | else 95 | if(buf_rptr[31:2] != buf_wptr[31:2]) begin 96 | if(~got_first) begin 97 | buf_rptr <= buf_wptr; 98 | got_first <= 1; 99 | end 100 | else 101 | if(!ram_burstcount && ~ram_waitrequest && ~ready) begin 102 | ram_address <= buf_addr[31:3] + buf_rptr[31:3]; 103 | ud <= buf_rptr[2]; 104 | ram_burstcount <= 1; 105 | ram_read <= 1; 106 | buf_rptr <= buf_rptr + 4; 107 | end 108 | end 109 | 110 | if(ready & ce_48k) begin 111 | {pcm_r,pcm_l} <= readdata; 112 | ready <= 0; 113 | end 114 | end 115 | 116 | reg ce_48k; 117 | always @(posedge ram_clk) begin 118 | reg [15:0] acc = 0; 119 | 120 | ce_48k <= 0; 121 | acc <= acc + 16'd48; 122 | if(acc >= 50000) begin 123 | acc <= acc - 16'd50000; 124 | ce_48k <= 1; 125 | end 126 | end 127 | 128 | endmodule 129 | -------------------------------------------------------------------------------- /src/FPGA_DIGDUG.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // FPGA DigDug (Top module) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module FPGA_DIGDUG 7 | ( 8 | input RESET, // RESET 9 | input MCLK, // Master Clock (48.0MHz) = VCLKx8 10 | 11 | input [7:0] INP0, // Control Panel 12 | input [7:0] INP1, 13 | input [7:0] DSW0, 14 | input [7:0] DSW1, 15 | 16 | input [8:0] PH, // PIXEL H 17 | input [8:0] PV, // PIXEL V 18 | output PCLK, // PIXEL CLOCK 19 | output [7:0] POUT, // PIXEL OUT 20 | 21 | output reg [7:0] SOUT, // SOUND OUT 22 | 23 | output [7:0] LED, // LEDs (for Debug) 24 | 25 | 26 | input ROMCL, // Downloaded ROM image 27 | input [15:0] ROMAD, 28 | input [7:0] ROMDT, 29 | input ROMEN 30 | ); 31 | 32 | // Common I/O Device Bus 33 | wire DEV_CL; 34 | wire [15:0] DEV_AD; 35 | wire DEV_RD; 36 | wire DEV_DV; 37 | wire [7:0] DEV_DO; 38 | wire DEV_WR; 39 | wire [7:0] DEV_DI; 40 | 41 | 42 | //----------------------------------------------- 43 | // CPUs 44 | //----------------------------------------------- 45 | wire [2:0] RSTS,IRQS,NMIS; 46 | 47 | DIGDUG_CORES cores 48 | ( 49 | .MCLK(MCLK), 50 | .RSTS(RSTS),.IRQS(IRQS),.NMIS(NMIS), 51 | 52 | .DEV_CL(DEV_CL),.DEV_AD(DEV_AD), 53 | .DEV_RD(DEV_RD),.DEV_DV(DEV_DV),.DEV_DO(DEV_DO), 54 | .DEV_WR(DEV_WR),.DEV_DI(DEV_DI), 55 | 56 | .ROMCL(ROMCL),.ROMAD(ROMAD),.ROMDT(ROMDT),.ROMEN(ROMEN) 57 | ); 58 | 59 | assign LED = { RSTS, IRQS[1:0], 1'b0, NMIS[2],NMIS[0] }; 60 | 61 | 62 | //----------------------------------------------- 63 | // Sound wave ROM 64 | //----------------------------------------------- 65 | wire WAVECL; 66 | wire [7:0] WAVEAD; 67 | wire [3:0] WAVEDT; 68 | 69 | DLROM #(8,4) wave(WAVECL,WAVEAD,WAVEDT, ROMCL,ROMAD[7:0],ROMDT,ROMEN & (ROMAD[15:8]==8'hD8)); 70 | 71 | 72 | //----------------------------------------------- 73 | // Common I/O Device Module 74 | //----------------------------------------------- 75 | wire PCMCLK; 76 | wire [7:0] PCMOUT; 77 | always @(posedge PCMCLK) SOUT <= PCMOUT; 78 | 79 | wire FGSCCL; 80 | wire [9:0] FGSCAD; 81 | wire [7:0] FGSCDT; 82 | 83 | wire SPATCL; 84 | wire [6:0] SPATAD; 85 | wire [23:0] SPATDT; 86 | 87 | wire [1:0] BG_SELECT; 88 | wire [1:0] BG_COLBNK; 89 | wire BG_CUTOFF; 90 | wire FG_CLMODE; 91 | 92 | wire VBLK; 93 | 94 | DIGDUG_IODEV iodev 95 | ( 96 | .RESET(RESET), 97 | .VBLK(VBLK), 98 | 99 | .INP0(INP0), 100 | .INP1(INP1), 101 | .DSW0(DSW0), 102 | .DSW1(DSW1), 103 | 104 | .CL(DEV_CL), // Access Clock: 24.0MHz 105 | .AD(DEV_AD),.WR(DEV_WR),.DI(DEV_DI), 106 | .RD(DEV_RD),.DV(DEV_DV),.DO(DEV_DO), 107 | 108 | .RSTS(RSTS),.IRQS(IRQS),.NMIS(NMIS), 109 | 110 | .CLK48M(MCLK),.PCMCLK(PCMCLK),.PCMOUT(PCMOUT), 111 | 112 | .WAVECL(WAVECL),.WAVEAD(WAVEAD),.WAVEDT(WAVEDT), 113 | 114 | .FGSCCL(FGSCCL),.FGSCAD(FGSCAD),.FGSCDT(FGSCDT), 115 | .SPATCL(SPATCL),.SPATAD(SPATAD),.SPATDT(SPATDT), 116 | 117 | .BG_SELECT(BG_SELECT),.BG_COLBNK(BG_COLBNK),.BG_CUTOFF(BG_CUTOFF), 118 | .FG_CLMODE(FG_CLMODE) 119 | ); 120 | 121 | 122 | //----------------------------------------------- 123 | // Video Module 124 | //----------------------------------------------- 125 | DIGDUG_VIDEO video 126 | ( 127 | .CLK48M(MCLK), 128 | .POSH(PH),.POSV(PV), 129 | 130 | .BG_SELECT(BG_SELECT),.BG_COLBNK(BG_COLBNK),.BG_CUTOFF(BG_CUTOFF), 131 | .FG_CLMODE(FG_CLMODE), 132 | 133 | .FGSCCL(FGSCCL),.FGSCAD(FGSCAD),.FGSCDT(FGSCDT), 134 | .SPATCL(SPATCL),.SPATAD(SPATAD),.SPATDT(SPATDT), 135 | 136 | .VBLK(VBLK),.PCLK(PCLK),.POUT(POUT), 137 | 138 | .ROMCL(ROMCL),.ROMAD(ROMAD),.ROMDT(ROMDT),.ROMEN(ROMEN) 139 | ); 140 | 141 | 142 | endmodule 143 | 144 | -------------------------------------------------------------------------------- /src/DIGDUG_VIDEO.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // FPGA DigDug (Video part) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module DIGDUG_VIDEO 7 | ( 8 | input CLK48M, 9 | input [8:0] POSH, 10 | input [8:0] POSV, 11 | 12 | input [1:0] BG_SELECT, 13 | input [1:0] BG_COLBNK, 14 | input BG_CUTOFF, 15 | input FG_CLMODE, 16 | 17 | output FGSCCL, 18 | output [9:0] FGSCAD, 19 | input [7:0] FGSCDT, 20 | 21 | output SPATCL, 22 | output [6:0] SPATAD, 23 | input [23:0] SPATDT, 24 | 25 | output VBLK, 26 | output PCLK, 27 | output [7:0] POUT, 28 | 29 | 30 | input ROMCL, // Downloaded ROM image 31 | input [15:0] ROMAD, 32 | input [7:0] ROMDT, 33 | input ROMEN 34 | ); 35 | 36 | //--------------------------------------- 37 | // Clock Generator 38 | //--------------------------------------- 39 | reg [2:0] clkdiv; 40 | always @( posedge CLK48M ) clkdiv <= clkdiv+1; 41 | wire VCLKx8 = CLK48M; 42 | wire VCLKx4 = clkdiv[0]; 43 | wire VCLKx2 = clkdiv[1]; 44 | wire VCLK = clkdiv[2]; 45 | 46 | 47 | //--------------------------------------- 48 | // Local Offset 49 | //--------------------------------------- 50 | reg [8:0] PH, PV; 51 | always@( posedge VCLK ) begin 52 | PH <= POSH+1; 53 | PV <= POSV+(POSH>=504); 54 | end 55 | 56 | 57 | //--------------------------------------- 58 | // VRAM Scan Address Generator 59 | //--------------------------------------- 60 | wire [5:0] SCOL = PH[8:3]-2; 61 | wire [5:0] SROW = PV[8:3]+2; 62 | wire [9:0] VSAD = SCOL[5] ? {SCOL[4:0],SROW[4:0]} : {SROW[4:0],SCOL[4:0]}; 63 | 64 | 65 | //--------------------------------------- 66 | // Sprite ScanLine Generator 67 | //--------------------------------------- 68 | wire [4:0] SPCOL; 69 | 70 | DIGDUG_SPRITE sprite 71 | ( 72 | .RCLK(VCLKx8),.VCLK(VCLK),.VCLKx2(VCLKx2), 73 | .POSH(PH-1),.POSV(PV), 74 | .SPATCL(SPATCL),.SPATAD(SPATAD),.SPATDT(SPATDT), 75 | 76 | .SPCOL(SPCOL), 77 | 78 | .ROMCL(ROMCL),.ROMAD(ROMAD),.ROMDT(ROMDT),.ROMEN(ROMEN) 79 | ); 80 | 81 | 82 | //--------------------------------------- 83 | // FG ScanLine Generator 84 | //--------------------------------------- 85 | reg [4:0] FGCOL; 86 | 87 | assign FGSCCL = VCLKx2; 88 | assign FGSCAD = VSAD; 89 | 90 | wire [10:0] FGCHAD = {1'b0,FGSCDT[6:0],PV[2:0]}; 91 | wire [7:0] FGCHDT; 92 | DLROM #(11,8) fgchip(~VCLKx2,FGCHAD,FGCHDT, ROMCL,ROMAD[10:0],ROMDT,ROMEN & (ROMAD[15:11]=={4'hD,1'b0})); 93 | wire [7:0] FGCHPX = FGCHDT >> (PH[2:0]); 94 | 95 | wire [3:0] FGCLUT = FG_CLMODE ? FGSCDT[3:0] : ({FGSCDT[7:5],1'b0}|{2'b00,FGSCDT[4],1'b0}); 96 | 97 | always @( posedge VCLKx2 ) FGCOL <= {FGCHPX[0],FGCLUT}; 98 | 99 | 100 | //--------------------------------------- 101 | // BG ScanLine Generator 102 | //--------------------------------------- 103 | wire [3:0] BGCOL; 104 | 105 | wire [11:0] BGSCAD = {BG_SELECT,VSAD}; 106 | wire [7:0] BGSCDT; 107 | DLROM #(12,8) bgscrn(VCLKx2,BGSCAD,BGSCDT, ROMCL,ROMAD[11:0],ROMDT,ROMEN & (ROMAD[15:12]==4'hB)); 108 | 109 | wire [11:0] BGCHAD = {BGSCDT,~PH[2],PV[2:0]}; 110 | wire [7:0] BGCHDT; 111 | DLROM #(12,8) bgchip(~VCLKx2,BGCHAD,BGCHDT, ROMCL,ROMAD[11:0],ROMDT,ROMEN & (ROMAD[15:12]==4'hC)); 112 | wire [7:0] BGCHPI = BGCHDT << (PH[1:0]); 113 | wire [1:0] BGCHPX = {BGCHPI[7],BGCHPI[3]}; 114 | 115 | wire [7:0] BGCLAD = BG_CUTOFF ? {6'h0F,BGCHPX} : {BG_COLBNK,BGSCDT[7:4],BGCHPX}; 116 | DLROM #(8,4) bgclut(VCLKx2,BGCLAD,BGCOL, ROMCL,ROMAD[7:0],ROMDT,ROMEN & (ROMAD[15:8]==8'hDA)); 117 | 118 | 119 | //--------------------------------------- 120 | // Color Mixer & Pixel Output 121 | //--------------------------------------- 122 | wire [4:0] CMIX = SPCOL[4] ? {1'b1,SPCOL[3:0]} : FGCOL[4] ? {1'b0,FGCOL[3:0]} : {1'b0,BGCOL}; 123 | 124 | DLROM #(5,8) palet( VCLK, CMIX, POUT, ROMCL,ROMAD[4:0],ROMDT,ROMEN & (ROMAD[15:5]=={8'hDB,3'b000}) ); 125 | assign PCLK = ~VCLK; 126 | assign VBLK = (PH<64)&(PV==224); 127 | 128 | endmodule 129 | 130 | -------------------------------------------------------------------------------- /Arcade-DigDug.srf: -------------------------------------------------------------------------------- 1 | { "" "" "" "Vip.Mixer: The MixerII register map changed in ACDS v16.0. Please refer to the VIP User Guide for details." { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 2 | { "" "" "" "Vip.Reset_Source.reset_sys: Associated reset sinks not declared" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 3 | { "" "" "" "Vip.Reset_Source.reset_warm: Associated reset sinks not declared" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 4 | { "" "" "" "Vip.Reset_Source.reset_cold: Associated reset sinks not declared" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 5 | { "" "" "" "Vip.Video_Output.control: Interrupt sender control.av_mm_control_interrupt is not connected to an interrupt receiver" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 6 | { "" "" "" "Vip.Video_Output: Interrupt sender Video_Output.status_update_irq is not connected to an interrupt receiver" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 7 | { "" "" "" "Vip.: You have exported the interface HPS.f2h_sdram1_data but not its associated reset interface. Export the driver(s) of HPS.h2f_reset" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 8 | { "" "" "" "Vip.: You have exported the interface HPS.f2h_sdram2_data but not its associated reset interface. Export the driver(s) of HPS.h2f_reset" { } { } 0 12251 "" 0 0 "Design Software" 0 -1 0 ""} 9 | { "" "" "" "Variable or input pin \"data_b\" is defined but never used." { } { } 0 287013 "" 0 0 "Design Software" 0 -1 0 ""} 10 | { "" "" "" "Variable or input pin \"data_a\" is defined but never used." { } { } 0 287013 "" 0 0 "Design Software" 0 -1 0 ""} 11 | { "" "" "" "Port \"extclk\" on the entity instantiation of \"cyclonev_pll\" is connected to a signal of width 1. The formal width of the signal in the module is 2. The extra bits will be left dangling without any fan-out logic." { } { } 0 12030 "" 0 0 "Design Software" 0 -1 0 ""} 12 | { "" "" "" "Port \"trs\" on the entity instantiation of \"statemachine\" is connected to a signal of width 2. The formal width of the signal in the module is 1. The extra bits will be ignored." { } { } 0 12020 "" 0 0 "Design Software" 0 -1 0 ""} 13 | { "" "" "" "Port \"reset_value\" on the entity instantiation of \"h_counter\" is connected to a signal of width 32. The formal width of the signal in the module is 16. The extra bits will be ignored." { } { } 0 12020 "" 0 0 "Design Software" 0 -1 0 ""} 14 | { "" "" "" "Overwriting existing clock: vip\|hps\|fpga_interfaces\|clocks_resets\|h2f_user0_clk" { } { } 0 332043 "" 0 0 "Design Software" 0 -1 0 ""} 15 | { "" "" "" "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 ""} 16 | { "" "" "" "Vip.vip: Module dependency loop involving: \"HPS\"" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 17 | { "" "" "" "alt_vip_common_frame_counter.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 18 | { "" "" "" "alt_vip_cvo_mode_banks.sv" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 19 | { "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 20 | { "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 21 | { "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 22 | { "" "" "" "genlock_enable_sync" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 23 | { "" "" "" "u_calculate_mode" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 24 | { "" "" "" "mode_banks" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 25 | { "" "" "" "RST port on the PLL is not properly connected" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 26 | { "" "" "" "alt_vip_cvo_core.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 27 | { "" "" "" "alt_vip_packet_transfer.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 28 | { "" "" "" "alt_vip_common_dc_mixed_widths_fifo.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 29 | { "" "" "" "vip_HPS_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} 30 | -------------------------------------------------------------------------------- /sys/video_mixer.sv: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2017 Sorgelig 4 | // 5 | // This program is GPL Licensed. See COPYING for the full license. 6 | // 7 | // 8 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 9 | 10 | `timescale 1ns / 1ps 11 | 12 | // 13 | // LINE_LENGTH: Length of display line in pixels 14 | // Usually it's length from HSync to HSync. 15 | // May be less if line_start is used. 16 | // 17 | // HALF_DEPTH: If =1 then color dept is 4 bits per component 18 | // For half depth 8 bits monochrome is available with 19 | // mono signal enabled and color = {G, R} 20 | 21 | module video_mixer 22 | #( 23 | parameter LINE_LENGTH = 768, 24 | parameter HALF_DEPTH = 0 25 | ) 26 | ( 27 | // master clock 28 | // it should be multiple by (ce_pix*4). 29 | input clk_sys, 30 | 31 | // Pixel clock or clock_enable (both are accepted). 32 | input ce_pix, 33 | output ce_pix_out, 34 | 35 | input scandoubler, 36 | 37 | // scanlines (00-none 01-25% 10-50% 11-75%) 38 | input [1:0] scanlines, 39 | 40 | // High quality 2x scaling 41 | input hq2x, 42 | 43 | // color 44 | input [DWIDTH:0] R, 45 | input [DWIDTH:0] G, 46 | input [DWIDTH:0] B, 47 | 48 | // Monochrome mode (for HALF_DEPTH only) 49 | input mono, 50 | 51 | // Positive pulses. 52 | input HSync, 53 | input VSync, 54 | input HBlank, 55 | input VBlank, 56 | 57 | // video output signals 58 | output reg [7:0] VGA_R, 59 | output reg [7:0] VGA_G, 60 | output reg [7:0] VGA_B, 61 | output reg VGA_VS, 62 | output reg VGA_HS, 63 | output reg VGA_DE 64 | ); 65 | 66 | localparam DWIDTH = HALF_DEPTH ? 3 : 7; 67 | 68 | wire [DWIDTH:0] R_sd; 69 | wire [DWIDTH:0] G_sd; 70 | wire [DWIDTH:0] B_sd; 71 | wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd; 72 | 73 | scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) sd 74 | ( 75 | .*, 76 | .hs_in(HSync), 77 | .vs_in(VSync), 78 | .hb_in(HBlank), 79 | .vb_in(VBlank), 80 | .r_in(R), 81 | .g_in(G), 82 | .b_in(B), 83 | 84 | .ce_pix_out(ce_pix_sd), 85 | .hs_out(hs_sd), 86 | .vs_out(vs_sd), 87 | .hb_out(hb_sd), 88 | .vb_out(vb_sd), 89 | .r_out(R_sd), 90 | .g_out(G_sd), 91 | .b_out(B_sd) 92 | ); 93 | 94 | wire [DWIDTH:0] rt = (scandoubler ? R_sd : R); 95 | wire [DWIDTH:0] gt = (scandoubler ? G_sd : G); 96 | wire [DWIDTH:0] bt = (scandoubler ? B_sd : B); 97 | 98 | generate 99 | if(HALF_DEPTH) begin 100 | wire [7:0] r = mono ? {gt,rt} : {rt,rt}; 101 | wire [7:0] g = mono ? {gt,rt} : {gt,gt}; 102 | wire [7:0] b = mono ? {gt,rt} : {bt,bt}; 103 | end else begin 104 | wire [7:0] r = rt; 105 | wire [7:0] g = gt; 106 | wire [7:0] b = bt; 107 | end 108 | endgenerate 109 | 110 | wire hs = (scandoubler ? hs_sd : HSync); 111 | wire vs = (scandoubler ? vs_sd : VSync); 112 | 113 | assign ce_pix_out = scandoubler ? ce_pix_sd : ce_pix; 114 | 115 | 116 | reg scanline = 0; 117 | always @(posedge clk_sys) begin 118 | reg old_hs, old_vs; 119 | 120 | old_hs <= hs; 121 | old_vs <= vs; 122 | 123 | if(old_hs && ~hs) scanline <= ~scanline; 124 | if(old_vs && ~vs) scanline <= 0; 125 | end 126 | 127 | wire hde = scandoubler ? ~hb_sd : ~HBlank; 128 | wire vde = scandoubler ? ~vb_sd : ~VBlank; 129 | 130 | always @(posedge clk_sys) begin 131 | reg old_hde; 132 | 133 | case(scanlines & {scanline, scanline}) 134 | 1: begin // reduce 25% = 1/2 + 1/4 135 | VGA_R <= {1'b0, r[7:1]} + {2'b00, r[7:2]}; 136 | VGA_G <= {1'b0, g[7:1]} + {2'b00, g[7:2]}; 137 | VGA_B <= {1'b0, b[7:1]} + {2'b00, b[7:2]}; 138 | end 139 | 140 | 2: begin // reduce 50% = 1/2 141 | VGA_R <= {1'b0, r[7:1]}; 142 | VGA_G <= {1'b0, g[7:1]}; 143 | VGA_B <= {1'b0, b[7:1]}; 144 | end 145 | 146 | 3: begin // reduce 75% = 1/4 147 | VGA_R <= {2'b00, r[7:2]}; 148 | VGA_G <= {2'b00, g[7:2]}; 149 | VGA_B <= {2'b00, b[7:2]}; 150 | end 151 | 152 | default: begin 153 | VGA_R <= r; 154 | VGA_G <= g; 155 | VGA_B <= b; 156 | end 157 | endcase 158 | 159 | VGA_VS <= vs; 160 | VGA_HS <= hs; 161 | 162 | old_hde <= hde; 163 | if(~old_hde && hde) VGA_DE <= vde; 164 | if(old_hde && ~hde) VGA_DE <= 0; 165 | end 166 | 167 | endmodule 168 | -------------------------------------------------------------------------------- /sys/pll_hdmi_cfg.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %Altera PLL Reconfig v17.1% 2 | // GENERATION: XML 3 | // pll_hdmi_cfg.v 4 | 5 | // Generated using ACDS version 17.1 590 6 | 7 | `timescale 1 ps / 1 ps 8 | module pll_hdmi_cfg #( 9 | parameter ENABLE_BYTEENABLE = 0, 10 | parameter BYTEENABLE_WIDTH = 4, 11 | parameter RECONFIG_ADDR_WIDTH = 6, 12 | parameter RECONFIG_DATA_WIDTH = 32, 13 | parameter reconf_width = 64, 14 | parameter WAIT_FOR_LOCK = 1 15 | ) ( 16 | input wire mgmt_clk, // mgmt_clk.clk 17 | input wire mgmt_reset, // mgmt_reset.reset 18 | output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest 19 | input wire mgmt_read, // .read 20 | input wire mgmt_write, // .write 21 | output wire [31:0] mgmt_readdata, // .readdata 22 | input wire [5:0] mgmt_address, // .address 23 | input wire [31:0] mgmt_writedata, // .writedata 24 | output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll 25 | input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll 26 | ); 27 | 28 | altera_pll_reconfig_top #( 29 | .device_family ("Cyclone V"), 30 | .ENABLE_MIF (0), 31 | .MIF_FILE_NAME ("sys/pll_hdmi_cfg.mif"), 32 | .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), 33 | .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), 34 | .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), 35 | .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), 36 | .reconf_width (reconf_width), 37 | .WAIT_FOR_LOCK (WAIT_FOR_LOCK) 38 | ) pll_hdmi_cfg_inst ( 39 | .mgmt_clk (mgmt_clk), // mgmt_clk.clk 40 | .mgmt_reset (mgmt_reset), // mgmt_reset.reset 41 | .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest 42 | .mgmt_read (mgmt_read), // .read 43 | .mgmt_write (mgmt_write), // .write 44 | .mgmt_readdata (mgmt_readdata), // .readdata 45 | .mgmt_address (mgmt_address), // .address 46 | .mgmt_writedata (mgmt_writedata), // .writedata 47 | .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll 48 | .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll 49 | .mgmt_byteenable (4'b0000) // (terminated) 50 | ); 51 | 52 | endmodule 53 | // Retrieval info: 54 | // 79 | // Retrieval info: 80 | // Retrieval info: 81 | // Retrieval info: 82 | // Retrieval info: 83 | // Retrieval info: 84 | // Retrieval info: 85 | // IPFS_FILES : pll_hdmi_cfg.vo 86 | // RELATED_FILES: pll_hdmi_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v 87 | -------------------------------------------------------------------------------- /sys/scandoubler.v: -------------------------------------------------------------------------------- 1 | // 2 | // scandoubler.v 3 | // 4 | // Copyright (c) 2015 Till Harbaum 5 | // Copyright (c) 2017-2019 Sorgelig 6 | // 7 | // This source file is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published 9 | // by the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This source file is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // TODO: Delay vsync one line 21 | 22 | module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) 23 | ( 24 | // system interface 25 | input clk_sys, 26 | input ce_pix, 27 | output ce_pix_out, 28 | 29 | input hq2x, 30 | 31 | // shifter video interface 32 | input hs_in, 33 | input vs_in, 34 | input hb_in, 35 | input vb_in, 36 | 37 | input [DWIDTH:0] r_in, 38 | input [DWIDTH:0] g_in, 39 | input [DWIDTH:0] b_in, 40 | input mono, 41 | 42 | // output interface 43 | output reg hs_out, 44 | output vs_out, 45 | output hb_out, 46 | output vb_out, 47 | output [DWIDTH:0] r_out, 48 | output [DWIDTH:0] g_out, 49 | output [DWIDTH:0] b_out 50 | ); 51 | 52 | 53 | localparam DWIDTH = HALF_DEPTH ? 3 : 7; 54 | 55 | assign vs_out = vso[3]; 56 | assign ce_pix_out = hq2x ? ce_x4 : ce_x2; 57 | 58 | //Compensate picture shift after HQ2x 59 | assign vb_out = vbo[3]; 60 | assign hb_out = hbo[6]; 61 | 62 | reg [7:0] pix_len = 0; 63 | reg [7:0] pix_cnt = 0; 64 | wire [7:0] pl = pix_len + 1'b1; 65 | wire [7:0] pc = pix_cnt + 1'b1; 66 | 67 | reg ce_x4, ce_x2, ce_x1; 68 | always @(negedge clk_sys) begin 69 | reg old_ce, valid, hs; 70 | reg [2:0] ce_cnt; 71 | 72 | reg [7:0] pixsz, pixsz2, pixsz4 = 0; 73 | 74 | if(~&pix_len) pix_len <= pl; 75 | if(~&pix_cnt) pix_cnt <= pc; 76 | 77 | ce_x4 <= 0; 78 | ce_x2 <= 0; 79 | ce_x1 <= 0; 80 | 81 | // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. 82 | if((pc == pixsz4) || (pc == pixsz2) || (pc == (pixsz2+pixsz4))) ce_x4 <= 1; 83 | if( pc == pixsz2) ce_x2 <= 1; 84 | 85 | old_ce <= ce_pix; 86 | if(~old_ce & ce_pix) begin 87 | if(valid & ~hb_in & ~vb_in) begin 88 | pixsz <= pl; 89 | pixsz2 <= {1'b0, pl[7:1]}; 90 | pixsz4 <= {2'b00, pl[7:2]}; 91 | end 92 | pix_len <= 0; 93 | valid <= 1; 94 | end 95 | 96 | if(hb_in | vb_in) valid <= 0; 97 | 98 | hs <= hs_out; 99 | if((~hs & hs_out) || (pc >= pixsz)) begin 100 | ce_x2 <= 1; 101 | ce_x4 <= 1; 102 | ce_x1 <= 1; 103 | pix_cnt <= 0; 104 | end 105 | end 106 | 107 | Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x 108 | ( 109 | .clk(clk_sys), 110 | .ce_x4(ce_x4), 111 | .inputpixel({b_d,g_d,r_d}), 112 | .mono(mono), 113 | .disable_hq2x(~hq2x), 114 | .reset_frame(vb_in), 115 | .reset_line(req_line_reset), 116 | .read_y(sd_line), 117 | .hblank(hbo[0]&hbo[8]), 118 | .outpixel({b_out,g_out,r_out}) 119 | ); 120 | 121 | reg [DWIDTH:0] r_d; 122 | reg [DWIDTH:0] g_d; 123 | reg [DWIDTH:0] b_d; 124 | 125 | reg [1:0] sd_line; 126 | reg [3:0] vbo; 127 | reg [3:0] vso; 128 | reg [8:0] hbo; 129 | 130 | reg req_line_reset; 131 | always @(posedge clk_sys) begin 132 | 133 | reg [31:0] hcnt; 134 | reg [30:0] sd_hcnt; 135 | reg [30:0] hs_start, hs_end; 136 | reg [30:0] hde_start, hde_end; 137 | 138 | reg hs, hb; 139 | 140 | if(ce_x4) begin 141 | hbo[8:1] <= hbo[7:0]; 142 | end 143 | 144 | // output counter synchronous to input and at twice the rate 145 | sd_hcnt <= sd_hcnt + 1'd1; 146 | if(sd_hcnt == hde_start) begin 147 | sd_hcnt <= 0; 148 | vbo[3:1] <= vbo[2:0]; 149 | end 150 | 151 | if(sd_hcnt == hs_end) begin 152 | sd_line <= sd_line + 1'd1; 153 | if(&vbo[3:2]) sd_line <= 1; 154 | vso[3:1] <= vso[2:0]; 155 | end 156 | 157 | if(sd_hcnt == hde_start)hbo[0] <= 0; 158 | if(sd_hcnt == hde_end) hbo[0] <= 1; 159 | 160 | // replicate horizontal sync at twice the speed 161 | if(sd_hcnt == hs_end) hs_out <= 0; 162 | if(sd_hcnt == hs_start) hs_out <= 1; 163 | 164 | hs <= hs_in; 165 | hb <= hb_in; 166 | 167 | if(ce_x1) begin 168 | req_line_reset <= hb_in; 169 | r_d <= r_in; 170 | g_d <= g_in; 171 | b_d <= b_in; 172 | end 173 | 174 | hcnt <= hcnt + 1'd1; 175 | if(hb && !hb_in) begin 176 | hde_start <= hcnt[31:1]; 177 | hbo[0] <= 0; 178 | hcnt <= 0; 179 | sd_hcnt <= 0; 180 | vbo <= {vbo[2:0],vb_in}; 181 | end 182 | 183 | if(!hb && hb_in) hde_end <= hcnt[31:1]; 184 | 185 | // falling edge of hsync indicates start of line 186 | if(hs && !hs_in) begin 187 | hs_end <= hcnt[31:1]; 188 | vso[0] <= vs_in; 189 | end 190 | 191 | // save position of rising edge 192 | if(!hs && hs_in) hs_start <= hcnt[31:1]; 193 | end 194 | 195 | endmodule 196 | -------------------------------------------------------------------------------- /src/wsg.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // Wave-base Sound Generator (3ch) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module WSG_3CH 7 | ( 8 | input CLK48M, 9 | input RESET, 10 | 11 | input CPUCLK, 12 | input [4:0] ADRS, 13 | input [3:0] DATA, 14 | input WR, 15 | 16 | output WROMCLK, 17 | output [7:0] WROMADR, 18 | input [3:0] WROMDAT, 19 | 20 | output PCMCLK, 21 | output [7:0] PCMOUT 22 | ); 23 | 24 | wire WSGCLKx4; 25 | WSGCLKGEN cgen( CLK48M, WSGCLKx4 ); 26 | 27 | wire [2:0] W0, W1, W2; 28 | wire [3:0] V0, V1, V2; 29 | wire [19:0] F0; 30 | wire [15:0] F1, F2; 31 | 32 | WSGREGS regs 33 | ( 34 | RESET, 35 | CPUCLK, ADRS, WR, DATA, 36 | 37 | W0, W1, W2, 38 | V0, V1, V2, 39 | F0, F1, F2 40 | ); 41 | 42 | WSGCORE core 43 | ( 44 | RESET, WSGCLKx4, 45 | WROMCLK, WROMADR, WROMDAT, 46 | 47 | W0, W1, W2, 48 | V0, V1, V2, 49 | F0, F1, F2, 50 | 51 | PCMCLK, PCMOUT 52 | ); 53 | 54 | endmodule 55 | 56 | 57 | module WSGREGS 58 | ( 59 | input RESET, 60 | input CPUCLK, 61 | input [4:0] ADRS, 62 | input WR, 63 | input [3:0] DATA, 64 | 65 | output reg [2:0] W0, 66 | output reg [2:0] W1, 67 | output reg [2:0] W2, 68 | 69 | output reg [3:0] V0, 70 | output reg [3:0] V1, 71 | output reg [3:0] V2, 72 | 73 | output reg [19:0] F0, 74 | output reg [15:0] F1, 75 | output reg [15:0] F2 76 | ); 77 | 78 | always @ ( posedge CPUCLK or posedge RESET ) begin 79 | 80 | if ( RESET ) begin 81 | 82 | W0 <= 0; 83 | W1 <= 0; 84 | W2 <= 0; 85 | 86 | F0 <= 0; 87 | F1 <= 0; 88 | F2 <= 0; 89 | 90 | V0 <= 0; 91 | V1 <= 0; 92 | V2 <= 0; 93 | 94 | end 95 | else begin 96 | 97 | if ( WR ) case ( ADRS ) 98 | 99 | 5'h05: W0 <= DATA[2:0]; 100 | 5'h0A: W1 <= DATA[2:0]; 101 | 5'h0F: W2 <= DATA[2:0]; 102 | 103 | 5'h15: V0 <= DATA; 104 | 5'h1A: V1 <= DATA; 105 | 5'h1F: V2 <= DATA; 106 | 107 | 5'h10: F0[3:0] <= DATA; 108 | 5'h11: F0[7:4] <= DATA; 109 | 5'h12: F0[11:8] <= DATA; 110 | 5'h13: F0[15:12] <= DATA; 111 | 5'h14: F0[19:16] <= DATA; 112 | 113 | 5'h16: F1[3:0] <= DATA; 114 | 5'h17: F1[7:4] <= DATA; 115 | 5'h18: F1[11:8] <= DATA; 116 | 5'h19: F1[15:12] <= DATA; 117 | 118 | 5'h1B: F2[3:0] <= DATA; 119 | 5'h1C: F2[7:4] <= DATA; 120 | 5'h1D: F2[11:8] <= DATA; 121 | 5'h1E: F2[15:12] <= DATA; 122 | 123 | default:; 124 | 125 | endcase 126 | 127 | end 128 | 129 | end 130 | 131 | endmodule 132 | 133 | 134 | module WSGCORE 135 | ( 136 | input RESET, 137 | input WSGCLKx4, 138 | 139 | output WROMCLK, 140 | output [7:0] WROMADR, 141 | input [3:0] WROMDAT, 142 | 143 | input [2:0] W0, 144 | input [2:0] W1, 145 | input [2:0] W2, 146 | 147 | input [3:0] V0, 148 | input [3:0] V1, 149 | input [3:0] V2, 150 | 151 | input [19:0] F0, 152 | input [15:0] F1, 153 | input [15:0] F2, 154 | 155 | output reg outclk, 156 | output reg [7:0] sndout 157 | ); 158 | 159 | reg [7:0] waveadr, cc1, cc2; 160 | 161 | reg [19:0] c0; 162 | reg [15:0] c1, c2; 163 | 164 | reg [3:0] wavevol; 165 | wire [7:0] waveout = wavevol * WROMDAT; 166 | 167 | reg [9:0] sndmix; 168 | wire [10:0] sndmixdown = { 1'b0, sndmix }; 169 | 170 | reg [1:0] phase; 171 | always @ ( posedge WSGCLKx4 or posedge RESET ) begin 172 | 173 | if ( RESET ) begin 174 | phase <= 0; 175 | sndout <= 0; 176 | outclk <= 0; 177 | cc1 <= 0; 178 | cc2 <= 0; 179 | end 180 | else begin 181 | 182 | case ( phase ) 183 | 184 | 0: begin 185 | sndout <= ( sndmixdown[9:2] | {8{sndmixdown[10]}} ); 186 | 187 | cc1 <= {W1,c1[15:11]}; 188 | cc2 <= {W2,c2[15:11]}; 189 | 190 | sndmix <= 0; 191 | waveadr <= {W0,c0[19:15]}; 192 | wavevol <= (F0!=0) ? V0 : 0; 193 | end 194 | 195 | 1: begin 196 | outclk <= 1'b1; 197 | sndmix <= sndmix + waveout; 198 | 199 | waveadr <= cc1; 200 | wavevol <= (F1!=0) ? V1 : 0; 201 | end 202 | 203 | 2: begin 204 | sndmix <= sndmix + waveout; 205 | 206 | waveadr <= cc2; 207 | wavevol <= (F2!=0) ? V2 : 0; 208 | end 209 | 210 | 3: begin 211 | outclk <= 0; 212 | sndmix <= sndmix + waveout; 213 | end 214 | 215 | default:; 216 | 217 | endcase 218 | 219 | phase <= phase+1; 220 | 221 | c0 <= c0 + F0; 222 | c1 <= c1 + F1; 223 | c2 <= c2 + F2; 224 | 225 | end 226 | 227 | end 228 | 229 | assign WROMCLK = ~WSGCLKx4; 230 | assign WROMADR = waveadr; 231 | 232 | endmodule 233 | 234 | 235 | /* 236 | Clock Generator 237 | in: 48000000Hz -> out: 96000Hz 238 | */ 239 | module WSGCLKGEN( input in, output reg out ); 240 | reg [7:0] count; 241 | always @( posedge in ) begin 242 | if (count > 8'd249) begin 243 | count <= count - 8'd249; 244 | out <= ~out; 245 | end 246 | else count <= count + 8'd1; 247 | end 248 | endmodule 249 | 250 | -------------------------------------------------------------------------------- /src/DIGDUG_CORES.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // FPGA DigDug (CPU part) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module DIGDUG_CORES 7 | ( 8 | input MCLK, // Clock (48.0MHz) 9 | 10 | input [2:0] RSTS, // RESET [2:0] 11 | input [2:0] IRQS, // IRQ [2:0] 12 | input [2:0] NMIS, // NMI [2:0] 13 | 14 | output DEV_CL, // I/O device Interface 15 | output [15:0] DEV_AD, 16 | output DEV_RD, 17 | input DEV_DV, 18 | input [7:0] DEV_DO, 19 | output DEV_WR, 20 | output [7:0] DEV_DI, 21 | 22 | 23 | input ROMCL, // Downloaded ROM image 24 | input [15:0] ROMAD, 25 | input [7:0] ROMDT, 26 | input ROMEN 27 | ); 28 | 29 | //----------------------------------------------- 30 | // CPU0 31 | //----------------------------------------------- 32 | wire CPU0CL; 33 | wire [15:0] CPU0AD; 34 | wire CPU0RD; 35 | wire CPU0DV; 36 | wire [7:0] CPU0DI; 37 | wire CPU0WR; 38 | wire [7:0] CPU0DO; 39 | 40 | wire [7:0] CPU0IR; 41 | DLROM #(14,8) rom0( DEV_CL, CPU0AD[13:0], CPU0IR, ROMCL,ROMAD[13:0],ROMDT,ROMEN & (ROMAD[15:14]==2'b00) ); 42 | 43 | wire NMI0; 44 | CPUNMIACK n0( RSTS[0], CPU0CL, CPU0AD, NMIS[0], NMI0 ); 45 | 46 | CPUCORE cpu0 ( 47 | .RESET(RSTS[0]),.CLK(CPU0CL), 48 | .IRQ(IRQS[0]),.NMI(NMI0), 49 | .AD(CPU0AD),.IR(CPU0IR), 50 | .RD(CPU0RD),.DV(CPU0DV),.DI(CPU0DI), 51 | .WR(CPU0WR),.DO(CPU0DO) 52 | ); 53 | 54 | 55 | //----------------------------------------------- 56 | // CPU1 57 | //----------------------------------------------- 58 | wire CPU1CL; 59 | wire [15:0] CPU1AD; 60 | wire CPU1RD; 61 | wire CPU1DV; 62 | wire [7:0] CPU1DI; 63 | wire CPU1WR; 64 | wire [7:0] CPU1DO; 65 | 66 | wire [7:0] CPU1IR; 67 | DLROM #(13,8) rom1( DEV_CL, CPU1AD[12:0], CPU1IR, ROMCL,ROMAD[12:0],ROMDT,ROMEN & (ROMAD[15:13]==3'b100) ); 68 | 69 | CPUCORE cpu1 ( 70 | .RESET(RSTS[1]),.CLK(CPU1CL), 71 | .IRQ(IRQS[1]),.NMI(NMIS[1]), 72 | .AD(CPU1AD),.IR(CPU1IR), 73 | .RD(CPU1RD),.DV(CPU1DV),.DI(CPU1DI), 74 | .WR(CPU1WR),.DO(CPU1DO) 75 | ); 76 | 77 | 78 | //----------------------------------------------- 79 | // CPU2 80 | //----------------------------------------------- 81 | wire CPU2CL; 82 | wire [15:0] CPU2AD; 83 | wire CPU2RD; 84 | wire CPU2DV; 85 | wire [7:0] CPU2DI; 86 | wire CPU2WR; 87 | wire [7:0] CPU2DO; 88 | 89 | wire [7:0] CPU2IR; 90 | DLROM #(12,8) rom2( DEV_CL, CPU2AD[11:0], CPU2IR, ROMCL,ROMAD[11:0],ROMDT,ROMEN & (ROMAD[15:12]==4'hA) ); 91 | 92 | wire NMI2; 93 | CPUNMIACK n2( RSTS[2], CPU2CL, CPU2AD, NMIS[2], NMI2 ); 94 | 95 | CPUCORE cpu2 ( 96 | .RESET(RSTS[2]),.CLK(CPU2CL), 97 | .IRQ(IRQS[2]),.NMI(NMI2), 98 | .AD(CPU2AD),.IR(CPU2IR), 99 | .RD(CPU2RD),.DV(CPU2DV),.DI(CPU2DI), 100 | .WR(CPU2WR),.DO(CPU2DO) 101 | ); 102 | 103 | 104 | //----------------------------------------------- 105 | // CPU Access Arbiter 106 | //----------------------------------------------- 107 | CPUARB arb 108 | ( 109 | MCLK, 110 | DEV_CL, DEV_AD, DEV_RD, DEV_DV, DEV_DO, DEV_WR, DEV_DI, 111 | CPU0CL, CPU0AD, CPU0RD, CPU0DV, CPU0DI, CPU0WR, CPU0DO, 112 | CPU1CL, CPU1AD, CPU1RD, CPU1DV, CPU1DI, CPU1WR, CPU1DO, 113 | CPU2CL, CPU2AD, CPU2RD, CPU2DV, CPU2DI, CPU2WR, CPU2DO 114 | ); 115 | 116 | endmodule 117 | 118 | 119 | module CPUARB 120 | ( 121 | input CLK48M, 122 | 123 | output DEV_CL, 124 | output [15:0] DEV_AD, 125 | output DEV_RD, 126 | input DEV_DV, 127 | input [7:0] DEV_DO, 128 | output DEV_WR, 129 | output [7:0] DEV_DI, 130 | 131 | output CPU0CL, 132 | input [15:0] CPU0AD, 133 | input CPU0RD, 134 | output CPU0DV, 135 | output [7:0] CPU0DI, 136 | input CPU0WR, 137 | input [7:0] CPU0DO, 138 | 139 | output CPU1CL, 140 | input [15:0] CPU1AD, 141 | input CPU1RD, 142 | output CPU1DV, 143 | output [7:0] CPU1DI, 144 | input CPU1WR, 145 | input [7:0] CPU1DO, 146 | 147 | output CPU2CL, 148 | input [15:0] CPU2AD, 149 | input CPU2RD, 150 | output CPU2DV, 151 | output [7:0] CPU2DI, 152 | input CPU2WR, 153 | input [7:0] CPU2DO 154 | ); 155 | 156 | reg [1:0] clkdiv; 157 | always @( posedge CLK48M ) clkdiv <= clkdiv+1; 158 | wire CLK24M = clkdiv[0]; 159 | wire CLK12M = clkdiv[1]; 160 | 161 | reg [3:0] CLKS = 4'b1000; 162 | reg [3:0] BUSS = 4'b0001; 163 | always @( posedge CLK12M ) CLKS <= {CLKS[2:0],CLKS[3]}; 164 | always @( negedge CLK12M ) BUSS <= {BUSS[2:0],BUSS[3]}; 165 | 166 | assign CPU0CL = CLKS[0]; 167 | assign CPU1CL = CLKS[1]; 168 | assign CPU2CL = CLKS[2]; 169 | 170 | assign DEV_CL = CLK24M; 171 | 172 | assign DEV_AD = BUSS[0] ? CPU0AD : 173 | BUSS[1] ? CPU1AD : 174 | BUSS[2] ? CPU2AD : 0; 175 | 176 | assign DEV_RD = BUSS[0] ? CPU0RD : 177 | BUSS[1] ? CPU1RD : 178 | BUSS[2] ? CPU2RD : 0; 179 | 180 | assign CPU0DV = BUSS[0] ? DEV_DV : 0; 181 | assign CPU1DV = BUSS[1] ? DEV_DV : 0; 182 | assign CPU2DV = BUSS[2] ? DEV_DV : 0; 183 | 184 | assign CPU0DI = BUSS[0] ? DEV_DO : 0; 185 | assign CPU1DI = BUSS[1] ? DEV_DO : 0; 186 | assign CPU2DI = BUSS[2] ? DEV_DO : 0; 187 | 188 | assign DEV_WR = BUSS[0] ? CPU0WR : 189 | BUSS[1] ? CPU1WR : 190 | BUSS[2] ? CPU2WR : 0; 191 | 192 | assign DEV_DI = BUSS[0] ? CPU0DO : 193 | BUSS[1] ? CPU1DO : 194 | BUSS[2] ? CPU2DO : 0; 195 | 196 | endmodule 197 | 198 | -------------------------------------------------------------------------------- /sys/osd.v: -------------------------------------------------------------------------------- 1 | // A simple OSD implementation. Can be hooked up between a cores 2 | // VGA output and the physical VGA pins 3 | 4 | module osd 5 | ( 6 | input clk_sys, 7 | 8 | input io_osd, 9 | input io_strobe, 10 | input [15:0] io_din, 11 | 12 | input clk_video, 13 | input [23:0] din, 14 | output [23:0] dout, 15 | input de_in, 16 | output reg de_out, 17 | output reg osd_status 18 | ); 19 | 20 | parameter OSD_COLOR = 3'd4; 21 | parameter OSD_X_OFFSET = 12'd0; 22 | parameter OSD_Y_OFFSET = 12'd0; 23 | 24 | localparam OSD_WIDTH = 12'd256; 25 | localparam OSD_HEIGHT = 12'd64; 26 | 27 | reg osd_enable; 28 | reg [7:0] osd_buffer[4096]; 29 | 30 | reg info = 0; 31 | reg [8:0] infoh; 32 | reg [8:0] infow; 33 | reg [11:0] infox; 34 | reg [21:0] infoy; 35 | reg [21:0] hrheight; 36 | 37 | always@(posedge clk_sys) begin 38 | reg [11:0] bcnt; 39 | reg [7:0] cmd; 40 | reg has_cmd; 41 | reg old_strobe; 42 | reg highres = 0; 43 | 44 | hrheight <= info ? infoh : (OSD_HEIGHT<> 9) > 1) ? (((cnt+1'b1) >> 9) - 1) : 0; 104 | pixcnt <= 0; 105 | end 106 | end 107 | 108 | reg [2:0] osd_de; 109 | reg osd_pixel; 110 | 111 | always @(posedge clk_video) begin 112 | reg deD; 113 | reg [1:0] osd_div; 114 | reg [1:0] multiscan; 115 | reg [7:0] osd_byte; 116 | reg [23:0] h_cnt; 117 | reg [21:0] v_cnt; 118 | reg [21:0] dsp_width; 119 | reg [21:0] osd_vcnt; 120 | reg [21:0] h_osd_start; 121 | reg [21:0] v_osd_start; 122 | reg [21:0] osd_hcnt; 123 | reg osd_de1,osd_de2; 124 | reg [1:0] osd_en; 125 | 126 | if(ce_pix) begin 127 | 128 | deD <= de_in; 129 | if(~&h_cnt) h_cnt <= h_cnt + 1'd1; 130 | 131 | if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1; 132 | if (h_cnt == h_osd_start) begin 133 | osd_de[0] <= osd_en[1] && hrheight && (osd_vcnt < hrheight); 134 | osd_hcnt <= 0; 135 | end 136 | if (osd_hcnt+1 == (info ? infow : OSD_WIDTH)) osd_de[0] <= 0; 137 | 138 | // falling edge of de 139 | if(!de_in && deD) dsp_width <= h_cnt[21:0]; 140 | 141 | // rising edge of de 142 | if(de_in && !deD) begin 143 | h_cnt <= 0; 144 | v_cnt <= v_cnt + 1'd1; 145 | h_osd_start <= info ? infox : (((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET - 2'd2); 146 | 147 | if(h_cnt > {dsp_width, 2'b00}) begin 148 | v_cnt <= 0; 149 | 150 | osd_en <= (osd_en << 1) | osd_enable; 151 | if(~osd_enable) osd_en <= 0; 152 | 153 | if(v_cnt<320) begin 154 | multiscan <= 0; 155 | v_osd_start <= info ? infoy : (((v_cnt-hrheight)>>1) + OSD_Y_OFFSET); 156 | end 157 | else if(v_cnt<640) begin 158 | multiscan <= 1; 159 | v_osd_start <= info ? (infoy<<1) : (((v_cnt-(hrheight<<1))>>1) + OSD_Y_OFFSET); 160 | end 161 | else if(v_cnt<960) begin 162 | multiscan <= 2; 163 | v_osd_start <= info ? (infoy + (infoy << 1)) : (((v_cnt-(hrheight + (hrheight<<1)))>>1) + OSD_Y_OFFSET); 164 | end 165 | else begin 166 | multiscan <= 3; 167 | v_osd_start <= info ? (infoy<<2) : (((v_cnt-(hrheight<<2))>>1) + OSD_Y_OFFSET); 168 | end 169 | end 170 | 171 | osd_div <= osd_div + 1'd1; 172 | if(osd_div == multiscan) begin 173 | osd_div <= 0; 174 | if(~&osd_vcnt) osd_vcnt <= osd_vcnt + 1'd1; 175 | end 176 | if(v_osd_start == (v_cnt+1'b1)) {osd_div, osd_vcnt} <= 0; 177 | end 178 | 179 | osd_byte <= osd_buffer[{osd_vcnt[6:3], osd_hcnt[7:0]}]; 180 | osd_pixel <= osd_byte[osd_vcnt[2:0]]; 181 | osd_de[2:1] <= osd_de[1:0]; 182 | end 183 | end 184 | 185 | reg [23:0] rdout; 186 | assign dout = rdout; 187 | 188 | always @(posedge clk_video) begin 189 | rdout <= ~osd_de[2] ? din : {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]}, 190 | {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]}, 191 | {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; 192 | de_out <= de_in; 193 | end 194 | 195 | endmodule 196 | -------------------------------------------------------------------------------- /src/cpu/tv80s.v: -------------------------------------------------------------------------------- 1 | // 2 | // TV80 8-Bit Microprocessor Core 3 | // Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) 4 | // 5 | // Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a 8 | // copy of this software and associated documentation files (the "Software"), 9 | // to deal in the Software without restriction, including without limitation 10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | // and/or sell copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | //`define TV80_REFRESH 26 | 27 | module tv80s (/*AUTOARG*/ 28 | // Outputs 29 | m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, do, 30 | // Inputs 31 | reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di 32 | ); 33 | 34 | parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB 35 | parameter T2Write = 1; // 0 => wr_n active in T3, /=0 => wr_n active in T2 36 | parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle 37 | 38 | 39 | input reset_n; 40 | input clk; 41 | input wait_n; 42 | input int_n; 43 | input nmi_n; 44 | input busrq_n; 45 | output m1_n; 46 | output mreq_n; 47 | output iorq_n; 48 | output rd_n; 49 | output wr_n; 50 | output rfsh_n; 51 | output halt_n; 52 | output busak_n; 53 | output [15:0] A; 54 | input [7:0] di; 55 | output [7:0] do; 56 | 57 | reg mreq_n; 58 | reg iorq_n; 59 | reg rd_n; 60 | reg wr_n; 61 | 62 | wire cen; 63 | wire intcycle_n; 64 | wire no_read; 65 | wire write; 66 | wire iorq; 67 | reg [7:0] di_reg; 68 | wire [6:0] mcycle; 69 | wire [6:0] tstate; 70 | 71 | assign cen = 1; 72 | 73 | tv80_core #(Mode, IOWait) i_tv80_core 74 | ( 75 | .cen (cen), 76 | .m1_n (m1_n), 77 | .iorq (iorq), 78 | .no_read (no_read), 79 | .write (write), 80 | .rfsh_n (rfsh_n), 81 | .halt_n (halt_n), 82 | .wait_n (wait_n), 83 | .int_n (int_n), 84 | .nmi_n (nmi_n), 85 | .reset_n (reset_n), 86 | .busrq_n (busrq_n), 87 | .busak_n (busak_n), 88 | .clk (clk), 89 | .IntE (), 90 | .stop (), 91 | .A (A), 92 | .dinst (di), 93 | .di (di_reg), 94 | .do (do), 95 | .mc (mcycle), 96 | .ts (tstate), 97 | .intcycle_n (intcycle_n) 98 | ); 99 | 100 | always @(posedge clk) 101 | begin 102 | if (!reset_n) 103 | begin 104 | rd_n <= #1 1'b1; 105 | wr_n <= #1 1'b1; 106 | iorq_n <= #1 1'b1; 107 | mreq_n <= #1 1'b1; 108 | di_reg <= #1 0; 109 | end 110 | else 111 | begin 112 | rd_n <= #1 1'b1; 113 | wr_n <= #1 1'b1; 114 | iorq_n <= #1 1'b1; 115 | mreq_n <= #1 1'b1; 116 | if (mcycle[0]) 117 | begin 118 | if (tstate[1] || (tstate[2] && wait_n == 1'b0)) 119 | begin 120 | rd_n <= #1 ~ intcycle_n; 121 | mreq_n <= #1 ~ intcycle_n; 122 | iorq_n <= #1 intcycle_n; 123 | end 124 | `ifdef TV80_REFRESH 125 | if (tstate[3]) 126 | mreq_n <= #1 1'b0; 127 | `endif 128 | end // if (mcycle[0]) 129 | else 130 | begin 131 | if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && no_read == 1'b0 && write == 1'b0) 132 | begin 133 | rd_n <= #1 1'b0; 134 | iorq_n <= #1 ~ iorq; 135 | mreq_n <= #1 iorq; 136 | end 137 | if (T2Write == 0) 138 | begin 139 | if (tstate[2] && write == 1'b1) 140 | begin 141 | wr_n <= #1 1'b0; 142 | iorq_n <= #1 ~ iorq; 143 | mreq_n <= #1 iorq; 144 | end 145 | end 146 | else 147 | begin 148 | if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && write == 1'b1) 149 | begin 150 | wr_n <= #1 1'b0; 151 | iorq_n <= #1 ~ iorq; 152 | mreq_n <= #1 iorq; 153 | end 154 | end // else: !if(T2write == 0) 155 | 156 | end // else: !if(mcycle[0]) 157 | 158 | if (tstate[2] && wait_n == 1'b1) 159 | di_reg <= #1 di; 160 | end // else: !if(!reset_n) 161 | end // always @ (posedge clk or negedge reset_n) 162 | 163 | endmodule // t80s 164 | 165 | -------------------------------------------------------------------------------- /src/DIGDUG_IODEV.v: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // FPGA DigDug (I/O device part) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //-------------------------------------------- 6 | module DIGDUG_IODEV 7 | ( 8 | input RESET, 9 | 10 | input [7:0] INP0, 11 | input [7:0] INP1, 12 | input [7:0] DSW0, 13 | input [7:0] DSW1, 14 | 15 | input VBLK, // V-BLANK 16 | 17 | input CL, // CPU Interface 18 | input [15:0] AD, 19 | input WR, 20 | input [7:0] DI, 21 | input RD, 22 | output DV, 23 | output [7:0] DO, 24 | 25 | output [2:0] RSTS, // CPU Reset Ctrl & Interrupt 26 | output [2:0] IRQS, 27 | output [2:0] NMIS, 28 | 29 | input CLK48M, 30 | output PCMCLK, 31 | output [7:0] PCMOUT, 32 | 33 | output WAVECL, // Wave ROM 34 | output [7:0] WAVEAD, 35 | input [3:0] WAVEDT, 36 | 37 | input FGSCCL, // FG VRAM 38 | input [9:0] FGSCAD, 39 | output [7:0] FGSCDT, 40 | 41 | input SPATCL, // SP ARAM 42 | input [6:0] SPATAD, 43 | output [23:0] SPATDT, 44 | 45 | output [1:0] BG_SELECT, // Video Ctrl. 46 | output [1:0] BG_COLBNK, 47 | output BG_CUTOFF, 48 | output FG_CLMODE 49 | 50 | ); 51 | 52 | // Work & Video Memory 53 | wire CSM0 = (AD[15:11] == 5'b1000_0); // $8000-$87FF 54 | wire CSM1 = (AD[15:11] == 5'b1000_1); // $8800-$8FFF 55 | wire CSM2 = (AD[15:11] == 5'b1001_0); // $9000-$97FF 56 | wire CSM3 = (AD[15:11] == 5'b1001_1); // $9800-$9FFF 57 | 58 | wire [10:0] MAD = AD[10:0]; 59 | wire [7:0] DOM0, DOM1, DOM2, DOM3; 60 | DPR2KV ram0( CL, MAD, CSM0, WR, DI, DOM0, FGSCCL, {1'b0,FGSCAD}, FGSCDT ); // (FGTX) $8000-$8300 61 | DPR2KV ram1( CL, MAD, CSM1, WR, DI, DOM1, SPATCL, {4'h7,SPATAD}, SPATDT[ 7: 0] ); // (SPA0) $8B80-$8BFF 62 | DPR2KV ram2( CL, MAD, CSM2, WR, DI, DOM2, SPATCL, {4'h7,SPATAD}, SPATDT[15: 8] ); // (SPA1) $9380-$93FF 63 | DPR2KV ram3( CL, MAD, CSM3, WR, DI, DOM3, SPATCL, {4'h7,SPATAD}, SPATDT[23:16] ); // (SPA2) $9B80-$9BFF 64 | 65 | 66 | // NAMCO WSG 67 | wire WSGWR =( AD[15:5] == 11'b0110_1000_000 ) & WR; // $6800-$681F 68 | WSG_3CH wsg( CLK48M, RESET, CL, AD[4:0], DI[3:0], WSGWR, WAVECL, WAVEAD, WAVEDT, PCMCLK, PCMOUT ); 69 | 70 | 71 | // NAMCO Custom I/O Chip 72 | wire CSCUSIO = (AD[15:9] == 7'b0111_000); // $70xx-$71xx 73 | wire [7:0] DOCUSIO; 74 | wire NMI0; 75 | DIGDUG_CUSIO cusio( RESET, VBLK, INP0, INP1, DSW0, DSW1, CL, CSCUSIO, WR, {AD[8],AD[3:0]}, DI, DOCUSIO, NMI0 ); 76 | 77 | 78 | // Video Ctrl Latches 79 | wire VLWR = (AD[15:3] == 13'b1010_0000_0000_0) & WR; // $A000-$A007 80 | DIGDUG_VLATCH vlats( RESET, CL, AD[2:0], VLWR, DI[0], BG_SELECT, BG_COLBNK, BG_CUTOFF, FG_CLMODE ); 81 | 82 | 83 | // CPU Ctrl Latches 84 | wire CLWR = (AD[15:3] == 13'b0110_1000_0010_0) & WR; // $6820-$6827 85 | wire NMI2; 86 | DIGDUG_CLATCH clats( RESET, CL, AD[2:0], CLWR, DI[0], VBLK, RSTS, IRQS, NMI2 ); 87 | 88 | 89 | // To CPU 90 | assign DV = CSM0|CSM1|CSM2|CSM3|CSCUSIO; 91 | assign DO = CSM0 ? DOM0 : CSM1 ? DOM1 : CSM2 ? DOM2 : CSM3 ? DOM3 : CSCUSIO ? DOCUSIO : 8'hFF; 92 | assign NMIS = {NMI2,1'b0,NMI0}; 93 | 94 | endmodule 95 | 96 | 97 | module DIGDUG_VLATCH 98 | ( 99 | input RESET, 100 | input CL, 101 | input [2:0] AD, 102 | input WR, 103 | input DI, 104 | 105 | output reg [1:0] BG_SELECT, 106 | output reg [1:0] BG_COLBNK, 107 | output reg BG_CUTOFF, 108 | output reg FG_CLMODE 109 | ); 110 | 111 | always @( posedge CL or posedge RESET ) begin 112 | if (RESET) begin 113 | BG_SELECT <= 2'b00; 114 | BG_COLBNK <= 2'b00; 115 | BG_CUTOFF <= 1'b0; 116 | FG_CLMODE <= 1'b0; 117 | end 118 | else begin 119 | if (WR) case(AD) 120 | 3'h0: BG_SELECT[0] <= DI; 121 | 3'h1: BG_SELECT[1] <= DI; 122 | 3'h2: FG_CLMODE <= DI; 123 | 3'h3: BG_CUTOFF <= DI; 124 | 3'h4: BG_COLBNK[0] <= DI; 125 | 3'h5: BG_COLBNK[1] <= DI; 126 | default:; 127 | endcase 128 | end 129 | end 130 | 131 | endmodule 132 | 133 | 134 | module DIGDUG_CLATCH 135 | ( 136 | input RESET, 137 | input CL, // 24MHz 138 | input [2:0] AD, 139 | input WR, 140 | input DI, 141 | 142 | input VBLK, 143 | output [2:0] RSTS, 144 | output [2:0] IRQS, 145 | output NMI2 146 | ); 147 | 148 | // OSC 120Hz 149 | `define H120FLOW (12500) 150 | reg [3:0] clkdiv; 151 | always @( posedge CL ) clkdiv <= clkdiv+1; 152 | reg [13:0] H120CNT; 153 | always @( posedge clkdiv[3] or posedge RESET ) begin 154 | if (RESET) H120CNT <= 0; 155 | else H120CNT <= (H120CNT==`H120FLOW) ? 0 : (H120CNT+1); 156 | end 157 | wire H120 = ( H120CNT >= (`H120FLOW-200) ) ? 1'b1 : 0; 158 | 159 | 160 | reg IRQ0EN, IRQ0LC; 161 | reg IRQ1EN, IRQ1LC; 162 | reg NMI2EN, NMI2LC; 163 | reg NMI0LC; 164 | 165 | reg C12RST = 1'b1; 166 | reg pH120; 167 | 168 | always @( posedge CL or posedge RESET ) begin 169 | if (RESET) begin 170 | IRQ0EN <= 1'b0; IRQ0LC <= 1'b0; 171 | IRQ1EN <= 1'b0; IRQ1LC <= 1'b0; 172 | NMI2EN <= 1'b0; NMI2LC <= 1'b0; 173 | C12RST <= 1'b1; NMI0LC <= 1'b0; 174 | pH120 <= 1'b0; 175 | end 176 | else begin 177 | if (WR) begin 178 | case(AD) 179 | 3'h0: begin IRQ0EN <= DI; if (~DI) IRQ0LC <= 1'b0; end 180 | 3'h1: begin IRQ1EN <= DI; if (~DI) IRQ1LC <= 1'b0; end 181 | 3'h2: begin NMI2EN <=~DI; if ( DI) NMI2LC <= 1'b0; end 182 | 3'h3: C12RST <= ~DI; 183 | default:; 184 | endcase 185 | end 186 | if (VBLK) begin IRQ0LC <= 1'b1; IRQ1LC <= 1'b1; end 187 | if ((pH120^H120)&H120) NMI2LC <= 1'b1; 188 | pH120 <= H120; 189 | end 190 | end 191 | 192 | assign RSTS = {{2{C12RST}},RESET}; 193 | assign IRQS = {1'b0,(IRQ1EN & IRQ1LC),(IRQ0EN & IRQ0LC)}; 194 | assign NMI2 = (NMI2EN & NMI2LC); 195 | 196 | endmodule 197 | 198 | -------------------------------------------------------------------------------- /sys/pll_hdmi_cfg.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" 2 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_TOOL_VERSION "17.1" 3 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "pll_hdmi_cfg" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi_cfg.cmp"] 5 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" 6 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 7 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_QSYS_MODE "UNKNOWN" 8 | set_global_assignment -name SYNTHESIS_ONLY_QIP ON 9 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_NAME "cGxsX2hkbWlfY2Zn" 10 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" 11 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" 12 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_INTERNAL "Off" 13 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" 14 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_VERSION "MTcuMQ==" 15 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" 16 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" 17 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" 18 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" 19 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" 20 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" 21 | set_global_assignment -entity "pll_hdmi_cfg" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" 22 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A=" 23 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" 24 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" 25 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_INTERNAL "Off" 26 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" 27 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_VERSION "MTcuMQ==" 28 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" 29 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ==" 30 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc=" 31 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" 32 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" 33 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" 34 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" 35 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" 36 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" 37 | 38 | set_global_assignment -library "pll_hdmi_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi_cfg.v"] 39 | set_global_assignment -library "pll_hdmi_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi_cfg/altera_pll_reconfig_top.v"] 40 | set_global_assignment -library "pll_hdmi_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi_cfg/altera_pll_reconfig_core.v"] 41 | set_global_assignment -library "pll_hdmi_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi_cfg/altera_std_synchronizer.v"] 42 | 43 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" 44 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_TOOL_VERSION "17.1" 45 | set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_hdmi_cfg" -name IP_TOOL_ENV "mwpim" 46 | -------------------------------------------------------------------------------- /sys/pll_hdmi_cfg/altera_std_synchronizer.v: -------------------------------------------------------------------------------- 1 | // (C) 2001-2017 Intel Corporation. All rights reserved. 2 | // Your use of Intel Corporation's design tools, logic functions and other 3 | // software and tools, and its AMPP partner logic functions, and any output 4 | // files from any of the foregoing (including device programming or simulation 5 | // files), and any associated documentation or information are expressly subject 6 | // to the terms and conditions of the Intel Program License Subscription 7 | // Agreement, Intel FPGA IP License Agreement, or other applicable 8 | // license agreement, including, without limitation, that your use is for the 9 | // sole purpose of programming logic devices manufactured by Intel and sold by 10 | // Intel or its authorized distributors. Please refer to the applicable 11 | // agreement for further details. 12 | 13 | 14 | // $Id: //acds/rel/17.1std/ip/sopc/components/primitives/altera_std_synchronizer/altera_std_synchronizer.v#1 $ 15 | // $Revision: #1 $ 16 | // $Date: 2017/07/30 $ 17 | // $Author: swbranch $ 18 | //----------------------------------------------------------------------------- 19 | // 20 | // File: altera_std_synchronizer.v 21 | // 22 | // Abstract: Single bit clock domain crossing synchronizer. 23 | // Composed of two or more flip flops connected in series. 24 | // Random metastable condition is simulated when the 25 | // __ALTERA_STD__METASTABLE_SIM macro is defined. 26 | // Use +define+__ALTERA_STD__METASTABLE_SIM argument 27 | // on the Verilog simulator compiler command line to 28 | // enable this mode. In addition, dfine the macro 29 | // __ALTERA_STD__METASTABLE_SIM_VERBOSE to get console output 30 | // with every metastable event generated in the synchronizer. 31 | // 32 | // Copyright (C) Altera Corporation 2009, All Rights Reserved 33 | //----------------------------------------------------------------------------- 34 | 35 | `timescale 1ns / 1ns 36 | 37 | module altera_std_synchronizer ( 38 | clk, 39 | reset_n, 40 | din, 41 | dout 42 | ); 43 | 44 | parameter depth = 3; // This value must be >= 2 ! 45 | 46 | input clk; 47 | input reset_n; 48 | input din; 49 | output dout; 50 | 51 | // QuartusII synthesis directives: 52 | // 1. Preserve all registers ie. do not touch them. 53 | // 2. Do not merge other flip-flops with synchronizer flip-flops. 54 | // QuartusII TimeQuest directives: 55 | // 1. Identify all flip-flops in this module as members of the synchronizer 56 | // to enable automatic metastability MTBF analysis. 57 | // 2. Cut all timing paths terminating on data input pin of the first flop din_s1. 58 | 59 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON; -name SDC_STATEMENT \"set_false_path -to [get_keepers {*altera_std_synchronizer:*|din_s1}]\" "} *) reg din_s1; 60 | 61 | (* altera_attribute = {"-name ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW; -name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON"} *) reg [depth-2:0] dreg; 62 | 63 | //synthesis translate_off 64 | initial begin 65 | if (depth <2) begin 66 | $display("%m: Error: synchronizer length: %0d less than 2.", depth); 67 | end 68 | end 69 | 70 | // the first synchronizer register is either a simple D flop for synthesis 71 | // and non-metastable simulation or a D flop with a method to inject random 72 | // metastable events resulting in random delay of [0,1] cycles 73 | 74 | `ifdef __ALTERA_STD__METASTABLE_SIM 75 | 76 | reg[31:0] RANDOM_SEED = 123456; 77 | wire next_din_s1; 78 | wire dout; 79 | reg din_last; 80 | reg random; 81 | event metastable_event; // hook for debug monitoring 82 | 83 | initial begin 84 | $display("%m: Info: Metastable event injection simulation mode enabled"); 85 | end 86 | 87 | always @(posedge clk) begin 88 | if (reset_n == 0) 89 | random <= $random(RANDOM_SEED); 90 | else 91 | random <= $random; 92 | end 93 | 94 | assign next_din_s1 = (din_last ^ din) ? random : din; 95 | 96 | always @(posedge clk or negedge reset_n) begin 97 | if (reset_n == 0) 98 | din_last <= 1'b0; 99 | else 100 | din_last <= din; 101 | end 102 | 103 | always @(posedge clk or negedge reset_n) begin 104 | if (reset_n == 0) 105 | din_s1 <= 1'b0; 106 | else 107 | din_s1 <= next_din_s1; 108 | end 109 | 110 | `else 111 | 112 | //synthesis translate_on 113 | always @(posedge clk or negedge reset_n) begin 114 | if (reset_n == 0) 115 | din_s1 <= 1'b0; 116 | else 117 | din_s1 <= din; 118 | end 119 | //synthesis translate_off 120 | 121 | `endif 122 | 123 | `ifdef __ALTERA_STD__METASTABLE_SIM_VERBOSE 124 | always @(*) begin 125 | if (reset_n && (din_last != din) && (random != din)) begin 126 | $display("%m: Verbose Info: metastable event @ time %t", $time); 127 | ->metastable_event; 128 | end 129 | end 130 | `endif 131 | 132 | //synthesis translate_on 133 | 134 | // the remaining synchronizer registers form a simple shift register 135 | // of length depth-1 136 | generate 137 | if (depth < 3) begin 138 | always @(posedge clk or negedge reset_n) begin 139 | if (reset_n == 0) 140 | dreg <= {depth-1{1'b0}}; 141 | else 142 | dreg <= din_s1; 143 | end 144 | end else begin 145 | always @(posedge clk or negedge reset_n) begin 146 | if (reset_n == 0) 147 | dreg <= {depth-1{1'b0}}; 148 | else 149 | dreg <= {dreg[depth-3:0], din_s1}; 150 | end 151 | end 152 | endgenerate 153 | 154 | assign dout = dreg[depth-2]; 155 | 156 | endmodule 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /src/DIGDUG_CUSIO.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------- 2 | // FPGA DigDug (Custom I/O chip emulation part) 3 | // 4 | // Copyright (c) 2017 MiSTer-X 5 | //----------------------------------------------- 6 | module DIGDUG_CUSIO 7 | ( 8 | input RESET, 9 | input VBLK, 10 | 11 | input [7:0] INP0, 12 | input [7:0] INP1, 13 | input [7:0] DSW0, 14 | input [7:0] DSW1, 15 | 16 | input CL, 17 | input CS, 18 | input WR, 19 | input [4:0] AD, 20 | input [7:0] DI, 21 | output [7:0] DO, 22 | output NMI0 23 | ); 24 | 25 | reg MODE; 26 | reg [7:0] COMMAND; 27 | 28 | reg [3:0] r2, r3, r4, r5; 29 | reg [3:0] LCINPCRE, LCREPCIN, LCOINS; 30 | reg [3:0] RCINPCRE, RCREPCIN, RCOINS; 31 | reg CREDITAT; 32 | reg [7:0] CREDITS; 33 | 34 | reg [11:0] CLK50uc; 35 | reg CLK50u; 36 | 37 | always @( posedge CL ) begin 38 | if (RESET) begin 39 | CLK50u <= 0; 40 | CLK50uc <= 0; 41 | end 42 | else begin 43 | if ( CLK50uc == 2200 ) CLK50u <= 1'b1; 44 | if ( CLK50uc == 2400 ) begin 45 | CLK50u <= 1'b0; 46 | CLK50uc <= 0; 47 | end 48 | else CLK50uc <= CLK50uc + 1; 49 | end 50 | end 51 | 52 | reg NMI0EN = 1'b0; 53 | assign NMI0 = NMI0EN & CLK50u; 54 | 55 | always @( posedge CL or posedge RESET ) begin 56 | if (RESET) begin 57 | NMI0EN <= 0; 58 | MODE <= 0; 59 | COMMAND <= 0; 60 | 61 | LCINPCRE <= 0; 62 | LCREPCIN <= 0; 63 | RCINPCRE <= 0; 64 | RCREPCIN <= 0; 65 | CREDITAT <= 0; 66 | end 67 | else begin 68 | if (CS&WR) begin 69 | if (AD[4]) begin 70 | // command write 71 | COMMAND <= DI; 72 | MODE <= (DI==8'hA1) ? 1'b1 : ((DI==8'hC1)|(DI==8'hE1)) ? 0 : MODE; 73 | NMI0EN <= (DI!=8'h10); 74 | end 75 | else begin 76 | // data write 77 | if (COMMAND == 8'hC1) case (AD[3:0]) 78 | 4'h2: r2 <= DI[3:0]; 79 | 4'h3: r3 <= DI[3:0]; 80 | 4'h4: r4 <= DI[3:0]; 81 | 4'h5: r5 <= DI[3:0]; 82 | 4'h8: begin 83 | LCINPCRE <= r2; 84 | LCREPCIN <= r3; 85 | RCINPCRE <= r4; 86 | RCREPCIN <= r5; 87 | CREDITAT <= 1'b1; 88 | end 89 | default:; 90 | endcase 91 | end 92 | end 93 | end 94 | end 95 | 96 | 97 | // data read 98 | wire [3:0] ADR = AD[3:0]; 99 | wire [7:0] NONE = 8'hFF; 100 | 101 | reg [7:0] SW_CC; 102 | reg [7:0] SW_P1; 103 | reg [7:0] SW_P2; 104 | 105 | wire [7:0] ST_CC; 106 | BCDCONV bcd( CREDITS, ST_CC[3:0], ST_CC[7:4] ); 107 | 108 | reg [7:0] ST_P1 = 8'hF8; 109 | reg [7:0] ST_P2 = 8'hF8; 110 | 111 | wire [7:0] SWMODE = (ADR==0) ? (~SW_CC) : 112 | (ADR==1) ? (~SW_P1) : 113 | (ADR==2) ? (~SW_P2) : NONE; 114 | 115 | wire [7:0] STMODE = (ADR==0) ? ST_CC : 116 | (ADR==1) ? ST_P1 : 117 | (ADR==2) ? ST_P2 : NONE; 118 | 119 | wire [7:0] READh71 = MODE ? SWMODE : STMODE; 120 | 121 | wire [7:0] READhB1 = {8{~(ADR<=2)}}; 122 | 123 | wire [7:0] READhD2 = (ADR==0) ? DSW0 : 124 | (ADR==1) ? DSW1 : NONE; 125 | 126 | wire [7:0] READDAT = (COMMAND == 8'h71) ? READh71 : 127 | (COMMAND == 8'hB1) ? READhB1 : 128 | (COMMAND == 8'hD2) ? READhD2 : NONE; 129 | 130 | assign DO = AD[4] ? COMMAND : READDAT; 131 | 132 | //------------------------------------------------------------ 133 | 134 | // INP0 = { SERVICE, 1'b0, m_coin2, m_coin1, m_start2, m_start1, m_pump2, m_pump1 }; 135 | // INP1 = { m_left2, m_down2, m_right2, m_up2, m_left1, m_down1, m_right1, m_up1 }; 136 | 137 | reg [15:0] pINP,piINP,piINP0,piINP1,piINP2; 138 | wire [15:0] nINP = {INP0,INP1}; 139 | wire [15:0] iINP = (pINP^nINP) & nINP; 140 | 141 | function [3:0] stick; 142 | input [3:0] stk; 143 | stick = stk[0] ? 0 : 144 | stk[1] ? 2 : 145 | stk[2] ? 4 : 146 | stk[3] ? 6 : 8; 147 | endfunction 148 | 149 | always @( posedge VBLK or posedge RESET ) begin 150 | if (RESET) begin 151 | LCOINS = 0; 152 | RCOINS = 0; 153 | CREDITS = 0; 154 | 155 | SW_CC <= 0; 156 | SW_P1 <= 0; 157 | SW_P2 <= 0; 158 | ST_P1 <= 8'hF8; 159 | ST_P2 <= 8'hF8; 160 | 161 | pINP <= 0; 162 | piINP <= 0; 163 | piINP0 <= 0; 164 | piINP1 <= 0; 165 | piINP2 <= 0; 166 | end 167 | else begin 168 | 169 | SW_CC <= {nINP[15],1'b0,piINP[11],piINP[10],2'b00,iINP[13],iINP[12]}; 170 | SW_P1 <= {2'b00, pINP[8], iINP[8],nINP[3:0]}; 171 | SW_P2 <= {2'b00, pINP[9], iINP[9],nINP[7:4]}; 172 | ST_P1 <= {2'b11,~pINP[8],~iINP[8],stick(nINP[3:0])}; 173 | ST_P2 <= {2'b11,~pINP[9],~iINP[9],stick(nINP[7:4])}; 174 | 175 | if (CREDITAT) begin 176 | if ( LCINPCRE > 0 ) begin 177 | if ( iINP[12] & ( CREDITS < 99 ) ) begin 178 | LCOINS = LCOINS+1; 179 | if ( LCOINS >= LCINPCRE ) begin 180 | CREDITS = CREDITS + LCREPCIN; 181 | LCOINS = 0; 182 | end 183 | end 184 | if ( iINP[13] & ( CREDITS < 99 ) ) begin 185 | RCOINS = RCOINS+1; 186 | if ( RCOINS >= RCINPCRE ) begin 187 | CREDITS = CREDITS + RCREPCIN; 188 | RCOINS = 0; 189 | end 190 | end 191 | end 192 | else CREDITS = 2; 193 | if ( CREDITS > 99 ) CREDITS = 99; 194 | 195 | if ( piINP[10] & (CREDITS >= 1) ) CREDITS = CREDITS-1; 196 | if ( piINP[11] & (CREDITS >= 2) ) CREDITS = CREDITS-2; 197 | end 198 | 199 | pINP <= nINP; 200 | piINP0 <= iINP; 201 | piINP1 <= piINP0; 202 | piINP2 <= piINP1; 203 | piINP <= piINP2; // delay start buttons 204 | 205 | end 206 | end 207 | 208 | endmodule 209 | 210 | 211 | 212 | //---------------------------------------- 213 | // BCD Converter 214 | //---------------------------------------- 215 | module add3(in,out); 216 | 217 | input [3:0] in; 218 | output [3:0] out; 219 | reg [3:0] out; 220 | 221 | always @ (in) 222 | case (in) 223 | 4'b0000: out <= 4'b0000; 224 | 4'b0001: out <= 4'b0001; 225 | 4'b0010: out <= 4'b0010; 226 | 4'b0011: out <= 4'b0011; 227 | 4'b0100: out <= 4'b0100; 228 | 4'b0101: out <= 4'b1000; 229 | 4'b0110: out <= 4'b1001; 230 | 4'b0111: out <= 4'b1010; 231 | 4'b1000: out <= 4'b1011; 232 | 4'b1001: out <= 4'b1100; 233 | default: out <= 4'b0000; 234 | endcase 235 | 236 | endmodule 237 | 238 | 239 | module BCDCONV(A,ONES,TENS); 240 | 241 | input [7:0] A; 242 | output [3:0] ONES, TENS; 243 | wire [3:0] c1,c2,c3,c4,c5,c6,c7; 244 | wire [3:0] d1,d2,d3,d4,d5,d6,d7; 245 | 246 | assign d1 = {1'b0,A[7:5]}; 247 | assign d2 = {c1[2:0],A[4]}; 248 | assign d3 = {c2[2:0],A[3]}; 249 | assign d4 = {c3[2:0],A[2]}; 250 | assign d5 = {c4[2:0],A[1]}; 251 | assign d6 = {1'b0,c1[3],c2[3],c3[3]}; 252 | assign d7 = {c6[2:0],c4[3]}; 253 | 254 | add3 m1(d1,c1); 255 | add3 m2(d2,c2); 256 | add3 m3(d3,c3); 257 | add3 m4(d4,c4); 258 | add3 m5(d5,c5); 259 | add3 m6(d6,c6); 260 | add3 m7(d7,c7); 261 | 262 | assign ONES = {c5[2:0],A[0]}; 263 | assign TENS = {c7[2:0],c5[3]}; 264 | 265 | endmodule 266 | 267 | -------------------------------------------------------------------------------- /sys/hdmi_config.sv: -------------------------------------------------------------------------------- 1 | 2 | module hdmi_config 3 | ( 4 | // Host Side 5 | input iCLK, 6 | input iRST_N, 7 | 8 | input dvi_mode, 9 | input audio_96k, 10 | 11 | // I2C Side 12 | output I2C_SCL, 13 | inout I2C_SDA 14 | ); 15 | 16 | // Internal Registers/Wires 17 | reg mI2C_GO = 0; 18 | wire mI2C_END; 19 | wire mI2C_ACK; 20 | reg [15:0] LUT_DATA; 21 | reg [7:0] LUT_INDEX = 0; 22 | 23 | i2c #(50_000_000, 20_000) i2c_av 24 | ( 25 | .CLK(iCLK), 26 | 27 | .I2C_SCL(I2C_SCL), // I2C CLOCK 28 | .I2C_SDA(I2C_SDA), // I2C DATA 29 | 30 | .I2C_DATA({8'h72,init_data[LUT_INDEX]}), // DATA:[SLAVE_ADDR,SUB_ADDR,DATA]. 0x72 is the Slave Address of the ADV7513 chip! 31 | .START(mI2C_GO), // START transfer 32 | .END(mI2C_END), // END transfer 33 | .ACK(mI2C_ACK) // ACK 34 | ); 35 | 36 | ////////////////////// Config Control //////////////////////////// 37 | always@(posedge iCLK or negedge iRST_N) begin 38 | reg [1:0] mSetup_ST = 0; 39 | 40 | if(!iRST_N) begin 41 | LUT_INDEX <= 0; 42 | mSetup_ST <= 0; 43 | mI2C_GO <= 0; 44 | end else begin 45 | if(init_data[LUT_INDEX] != 16'hFFFF) begin 46 | case(mSetup_ST) 47 | 0: begin 48 | mI2C_GO <= 1; 49 | mSetup_ST <= 1; 50 | end 51 | 1: if(~mI2C_END) mSetup_ST <= 2; 52 | 2: begin 53 | mI2C_GO <= 0; 54 | if(mI2C_END) begin 55 | mSetup_ST <= 0; 56 | if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1; 57 | end 58 | end 59 | endcase 60 | end 61 | end 62 | end 63 | 64 | //////////////////////////////////////////////////////////////////// 65 | ///////////////////// Config Data LUT ////////////////////////// 66 | 67 | wire [15:0] init_data[58] = 68 | '{ 69 | 16'h9803, // ADI required Write. 70 | 71 | {8'hD6, 8'b1100_0000}, // [7:6] HPD Control... 72 | // 00 = HPD is from both HPD pin or CDC HPD 73 | // 01 = HPD is from CDC HPD 74 | // 10 = HPD is from HPD pin 75 | // 11 = HPD is always high 76 | 77 | 16'h4110, // Power Down control 78 | 16'h9A70, // ADI required Write. 79 | 16'h9C30, // ADI required Write. 80 | {8'h9D, 8'b0110_0001}, // [7:4] must be b0110!. 81 | // [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid! 82 | // [1:0] must be b01! 83 | 16'hA2A4, // ADI required Write. 84 | 16'hA3A4, // ADI required Write. 85 | 16'hE0D0, // ADI required Write. 86 | 87 | 88 | 16'h35_40, 89 | 16'h36_D9, 90 | 16'h37_0A, 91 | 16'h38_00, 92 | 16'h39_2D, 93 | 16'h3A_00, 94 | 95 | {8'h16, 8'b0011_1000}, // Output Format 444 [7]=0. 96 | // [6] must be 0! 97 | // Colour Depth for Input Video data [5:4] b11 = 8-bit. 98 | // Input Style [3:2] b10 = Style 1 (ignored when using 444 input). 99 | // DDR Input Edge falling [1]=0 (not using DDR atm). 100 | // Output Colour Space RGB [0]=0. 101 | 102 | {8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 103 | 104 | {8'h18, 8'b0100_0110}, // CSC disabled [7]=0. 105 | // CSC Scaling Factor [6:5] b10 = +/- 4.0, -16384 - 16380. 106 | // CSC Equation 3 [4:0] b00110. 107 | 108 | 109 | {8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx. 110 | 111 | 16'h4000, // General Control Packet Enable 112 | 113 | {8'h48, 8'b0000_1000}, // [6]=0 Normal bus order! 114 | // [5] DDR Alignment. 115 | // [4:3] b01 Data right justified (for YCbCr 422 input modes). 116 | 117 | 16'h49A8, // ADI required Write. 118 | 16'h4C00, // ADI required Write. 119 | 120 | {8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4]. 121 | // AVI InfoFrame Valid [4]. 122 | // Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both. 123 | // Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None. 124 | 125 | 16'h7301, 126 | 127 | {8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled. 128 | 129 | 16'h9902, // ADI required Write. 130 | 16'h9B18, // ADI required Write. 131 | 132 | 16'h9F00, // ADI required Write. 133 | 134 | {8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled. 135 | 136 | 16'hA408, // ADI required Write. 137 | 16'hA504, // ADI required Write. 138 | 16'hA600, // ADI required Write. 139 | 16'hA700, // ADI required Write. 140 | 16'hA800, // ADI required Write. 141 | 16'hA900, // ADI required Write. 142 | 16'hAA00, // ADI required Write. 143 | 16'hAB40, // ADI required Write. 144 | 145 | {8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled. 146 | // [6:5] must be b00! 147 | // [4]=0 Current frame is unencrypted 148 | // [3:2] must be b01! 149 | // [1]=1 HDMI Mode. 150 | // [0] must be b0! 151 | 152 | 16'hB900, // ADI required Write. 153 | 154 | {8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay... 155 | // b000 = -1.2ns. 156 | // b001 = -0.8ns. 157 | // b010 = -0.4ns. 158 | // b011 = No delay. 159 | // b100 = 0.4ns. 160 | // b101 = 0.8ns. 161 | // b110 = 1.2ns. 162 | // b111 = 1.6ns. 163 | 164 | 16'hBB00, // ADI required Write. 165 | 166 | 16'hDE9C, // ADI required Write. 167 | 16'hE460, // ADI required Write. 168 | 16'hFA7D, // Nbr of times to search for good phase 169 | 170 | 171 | // (Audio stuff on Programming Guide, Page 66)... 172 | 173 | {8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S. 174 | // [3:2] Audio Mode. (HBR stuff, leave at 00!). 175 | 176 | {8'h0B, 8'b0000_1110}, // 177 | 178 | {8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register. 179 | // [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register. 180 | // [2] 1 = I2S0 Enable. 181 | // [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES. 182 | 183 | {8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified. 184 | {8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits. 185 | {8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. 186 | // Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs. 187 | 188 | // Audio Clock Config 189 | 16'h0100, // 190 | audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144 191 | 16'h0300, // 192 | 193 | 16'h0701, // 194 | 16'h0822, // Set CTS Value 74250 195 | 16'h090A, // 196 | 197 | 16'hFFFF // END 198 | }; 199 | 200 | //////////////////////////////////////////////////////////////////// 201 | 202 | endmodule -------------------------------------------------------------------------------- /sys/pll_hdmi/pll_hdmi_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module pll_hdmi_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'locked' 14 | output wire locked, 15 | 16 | // interface 'reconfig_to_pll' 17 | input wire [63:0] reconfig_to_pll, 18 | 19 | // interface 'reconfig_from_pll' 20 | output wire [63:0] reconfig_from_pll 21 | ); 22 | 23 | altera_pll #( 24 | .fractional_vco_multiplier("true"), 25 | .reference_clock_frequency("50.0 MHz"), 26 | .pll_fractional_cout(32), 27 | .pll_dsm_out_sel("1st_order"), 28 | .operation_mode("direct"), 29 | .number_of_clocks(1), 30 | .output_clock_frequency0("148.500000 MHz"), 31 | .phase_shift0("0 ps"), 32 | .duty_cycle0(50), 33 | .output_clock_frequency1("0 MHz"), 34 | .phase_shift1("0 ps"), 35 | .duty_cycle1(50), 36 | .output_clock_frequency2("0 MHz"), 37 | .phase_shift2("0 ps"), 38 | .duty_cycle2(50), 39 | .output_clock_frequency3("0 MHz"), 40 | .phase_shift3("0 ps"), 41 | .duty_cycle3(50), 42 | .output_clock_frequency4("0 MHz"), 43 | .phase_shift4("0 ps"), 44 | .duty_cycle4(50), 45 | .output_clock_frequency5("0 MHz"), 46 | .phase_shift5("0 ps"), 47 | .duty_cycle5(50), 48 | .output_clock_frequency6("0 MHz"), 49 | .phase_shift6("0 ps"), 50 | .duty_cycle6(50), 51 | .output_clock_frequency7("0 MHz"), 52 | .phase_shift7("0 ps"), 53 | .duty_cycle7(50), 54 | .output_clock_frequency8("0 MHz"), 55 | .phase_shift8("0 ps"), 56 | .duty_cycle8(50), 57 | .output_clock_frequency9("0 MHz"), 58 | .phase_shift9("0 ps"), 59 | .duty_cycle9(50), 60 | .output_clock_frequency10("0 MHz"), 61 | .phase_shift10("0 ps"), 62 | .duty_cycle10(50), 63 | .output_clock_frequency11("0 MHz"), 64 | .phase_shift11("0 ps"), 65 | .duty_cycle11(50), 66 | .output_clock_frequency12("0 MHz"), 67 | .phase_shift12("0 ps"), 68 | .duty_cycle12(50), 69 | .output_clock_frequency13("0 MHz"), 70 | .phase_shift13("0 ps"), 71 | .duty_cycle13(50), 72 | .output_clock_frequency14("0 MHz"), 73 | .phase_shift14("0 ps"), 74 | .duty_cycle14(50), 75 | .output_clock_frequency15("0 MHz"), 76 | .phase_shift15("0 ps"), 77 | .duty_cycle15(50), 78 | .output_clock_frequency16("0 MHz"), 79 | .phase_shift16("0 ps"), 80 | .duty_cycle16(50), 81 | .output_clock_frequency17("0 MHz"), 82 | .phase_shift17("0 ps"), 83 | .duty_cycle17(50), 84 | .pll_type("Cyclone V"), 85 | .pll_subtype("Reconfigurable"), 86 | .m_cnt_hi_div(4), 87 | .m_cnt_lo_div(4), 88 | .n_cnt_hi_div(256), 89 | .n_cnt_lo_div(256), 90 | .m_cnt_bypass_en("false"), 91 | .n_cnt_bypass_en("true"), 92 | .m_cnt_odd_div_duty_en("false"), 93 | .n_cnt_odd_div_duty_en("false"), 94 | .c_cnt_hi_div0(2), 95 | .c_cnt_lo_div0(1), 96 | .c_cnt_prst0(1), 97 | .c_cnt_ph_mux_prst0(0), 98 | .c_cnt_in_src0("ph_mux_clk"), 99 | .c_cnt_bypass_en0("false"), 100 | .c_cnt_odd_div_duty_en0("true"), 101 | .c_cnt_hi_div1(1), 102 | .c_cnt_lo_div1(1), 103 | .c_cnt_prst1(1), 104 | .c_cnt_ph_mux_prst1(0), 105 | .c_cnt_in_src1("ph_mux_clk"), 106 | .c_cnt_bypass_en1("true"), 107 | .c_cnt_odd_div_duty_en1("false"), 108 | .c_cnt_hi_div2(1), 109 | .c_cnt_lo_div2(1), 110 | .c_cnt_prst2(1), 111 | .c_cnt_ph_mux_prst2(0), 112 | .c_cnt_in_src2("ph_mux_clk"), 113 | .c_cnt_bypass_en2("true"), 114 | .c_cnt_odd_div_duty_en2("false"), 115 | .c_cnt_hi_div3(1), 116 | .c_cnt_lo_div3(1), 117 | .c_cnt_prst3(1), 118 | .c_cnt_ph_mux_prst3(0), 119 | .c_cnt_in_src3("ph_mux_clk"), 120 | .c_cnt_bypass_en3("true"), 121 | .c_cnt_odd_div_duty_en3("false"), 122 | .c_cnt_hi_div4(1), 123 | .c_cnt_lo_div4(1), 124 | .c_cnt_prst4(1), 125 | .c_cnt_ph_mux_prst4(0), 126 | .c_cnt_in_src4("ph_mux_clk"), 127 | .c_cnt_bypass_en4("true"), 128 | .c_cnt_odd_div_duty_en4("false"), 129 | .c_cnt_hi_div5(1), 130 | .c_cnt_lo_div5(1), 131 | .c_cnt_prst5(1), 132 | .c_cnt_ph_mux_prst5(0), 133 | .c_cnt_in_src5("ph_mux_clk"), 134 | .c_cnt_bypass_en5("true"), 135 | .c_cnt_odd_div_duty_en5("false"), 136 | .c_cnt_hi_div6(1), 137 | .c_cnt_lo_div6(1), 138 | .c_cnt_prst6(1), 139 | .c_cnt_ph_mux_prst6(0), 140 | .c_cnt_in_src6("ph_mux_clk"), 141 | .c_cnt_bypass_en6("true"), 142 | .c_cnt_odd_div_duty_en6("false"), 143 | .c_cnt_hi_div7(1), 144 | .c_cnt_lo_div7(1), 145 | .c_cnt_prst7(1), 146 | .c_cnt_ph_mux_prst7(0), 147 | .c_cnt_in_src7("ph_mux_clk"), 148 | .c_cnt_bypass_en7("true"), 149 | .c_cnt_odd_div_duty_en7("false"), 150 | .c_cnt_hi_div8(1), 151 | .c_cnt_lo_div8(1), 152 | .c_cnt_prst8(1), 153 | .c_cnt_ph_mux_prst8(0), 154 | .c_cnt_in_src8("ph_mux_clk"), 155 | .c_cnt_bypass_en8("true"), 156 | .c_cnt_odd_div_duty_en8("false"), 157 | .c_cnt_hi_div9(1), 158 | .c_cnt_lo_div9(1), 159 | .c_cnt_prst9(1), 160 | .c_cnt_ph_mux_prst9(0), 161 | .c_cnt_in_src9("ph_mux_clk"), 162 | .c_cnt_bypass_en9("true"), 163 | .c_cnt_odd_div_duty_en9("false"), 164 | .c_cnt_hi_div10(1), 165 | .c_cnt_lo_div10(1), 166 | .c_cnt_prst10(1), 167 | .c_cnt_ph_mux_prst10(0), 168 | .c_cnt_in_src10("ph_mux_clk"), 169 | .c_cnt_bypass_en10("true"), 170 | .c_cnt_odd_div_duty_en10("false"), 171 | .c_cnt_hi_div11(1), 172 | .c_cnt_lo_div11(1), 173 | .c_cnt_prst11(1), 174 | .c_cnt_ph_mux_prst11(0), 175 | .c_cnt_in_src11("ph_mux_clk"), 176 | .c_cnt_bypass_en11("true"), 177 | .c_cnt_odd_div_duty_en11("false"), 178 | .c_cnt_hi_div12(1), 179 | .c_cnt_lo_div12(1), 180 | .c_cnt_prst12(1), 181 | .c_cnt_ph_mux_prst12(0), 182 | .c_cnt_in_src12("ph_mux_clk"), 183 | .c_cnt_bypass_en12("true"), 184 | .c_cnt_odd_div_duty_en12("false"), 185 | .c_cnt_hi_div13(1), 186 | .c_cnt_lo_div13(1), 187 | .c_cnt_prst13(1), 188 | .c_cnt_ph_mux_prst13(0), 189 | .c_cnt_in_src13("ph_mux_clk"), 190 | .c_cnt_bypass_en13("true"), 191 | .c_cnt_odd_div_duty_en13("false"), 192 | .c_cnt_hi_div14(1), 193 | .c_cnt_lo_div14(1), 194 | .c_cnt_prst14(1), 195 | .c_cnt_ph_mux_prst14(0), 196 | .c_cnt_in_src14("ph_mux_clk"), 197 | .c_cnt_bypass_en14("true"), 198 | .c_cnt_odd_div_duty_en14("false"), 199 | .c_cnt_hi_div15(1), 200 | .c_cnt_lo_div15(1), 201 | .c_cnt_prst15(1), 202 | .c_cnt_ph_mux_prst15(0), 203 | .c_cnt_in_src15("ph_mux_clk"), 204 | .c_cnt_bypass_en15("true"), 205 | .c_cnt_odd_div_duty_en15("false"), 206 | .c_cnt_hi_div16(1), 207 | .c_cnt_lo_div16(1), 208 | .c_cnt_prst16(1), 209 | .c_cnt_ph_mux_prst16(0), 210 | .c_cnt_in_src16("ph_mux_clk"), 211 | .c_cnt_bypass_en16("true"), 212 | .c_cnt_odd_div_duty_en16("false"), 213 | .c_cnt_hi_div17(1), 214 | .c_cnt_lo_div17(1), 215 | .c_cnt_prst17(1), 216 | .c_cnt_ph_mux_prst17(0), 217 | .c_cnt_in_src17("ph_mux_clk"), 218 | .c_cnt_bypass_en17("true"), 219 | .c_cnt_odd_div_duty_en17("false"), 220 | .pll_vco_div(2), 221 | .pll_cp_current(20), 222 | .pll_bwctrl(4000), 223 | .pll_output_clk_frequency("445.499999 MHz"), 224 | .pll_fractional_division("3908420153"), 225 | .mimic_fbclk_type("none"), 226 | .pll_fbclk_mux_1("glb"), 227 | .pll_fbclk_mux_2("m_cnt"), 228 | .pll_m_cnt_in_src("ph_mux_clk"), 229 | .pll_slf_rst("true") 230 | ) altera_pll_i ( 231 | .rst (rst), 232 | .outclk ({outclk_0}), 233 | .locked (locked), 234 | .reconfig_to_pll (reconfig_to_pll), 235 | .fboutclk ( ), 236 | .fbclk (1'b0), 237 | .refclk (refclk), 238 | .reconfig_from_pll (reconfig_from_pll) 239 | ); 240 | endmodule 241 | 242 | -------------------------------------------------------------------------------- /Arcade-DigDug.sv: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // Arcade: DigDug 3 | // 4 | // Original implimentation and port to MiSTer by MiSTer-X 2019 5 | //============================================================================ 6 | 7 | module emu 8 | ( 9 | //Master input clock 10 | input CLK_50M, 11 | 12 | //Async reset from top-level module. 13 | //Can be used as initial reset. 14 | input RESET, 15 | 16 | //Must be passed to hps_io module 17 | inout [44:0] HPS_BUS, 18 | 19 | //Base video clock. Usually equals to CLK_SYS. 20 | output VGA_CLK, 21 | 22 | //Multiple resolutions are supported using different VGA_CE rates. 23 | //Must be based on CLK_VIDEO 24 | output VGA_CE, 25 | 26 | output [7:0] VGA_R, 27 | output [7:0] VGA_G, 28 | output [7:0] VGA_B, 29 | output VGA_HS, 30 | output VGA_VS, 31 | output VGA_DE, // = ~(VBlank | HBlank) 32 | 33 | //Base video clock. Usually equals to CLK_SYS. 34 | output HDMI_CLK, 35 | 36 | //Multiple resolutions are supported using different HDMI_CE rates. 37 | //Must be based on CLK_VIDEO 38 | output HDMI_CE, 39 | 40 | output [7:0] HDMI_R, 41 | output [7:0] HDMI_G, 42 | output [7:0] HDMI_B, 43 | output HDMI_HS, 44 | output HDMI_VS, 45 | output HDMI_DE, // = ~(VBlank | HBlank) 46 | output [1:0] HDMI_SL, // scanlines fx 47 | 48 | //Video aspect ratio for HDMI. Most retro systems have ratio 4:3. 49 | output [7:0] HDMI_ARX, 50 | output [7:0] HDMI_ARY, 51 | 52 | output LED_USER, // 1 - ON, 0 - OFF. 53 | 54 | // b[1]: 0 - LED status is system status OR'd with b[0] 55 | // 1 - LED status is controled solely by b[0] 56 | // hint: supply 2'b00 to let the system control the LED. 57 | output [1:0] LED_POWER, 58 | output [1:0] LED_DISK, 59 | 60 | output [15:0] AUDIO_L, 61 | output [15:0] AUDIO_R, 62 | output AUDIO_S // 1 - signed audio samples, 0 - unsigned 63 | ); 64 | 65 | assign LED_USER = ioctl_download; 66 | assign LED_DISK = 0; 67 | assign LED_POWER = 0; 68 | 69 | assign HDMI_ARX = status[1] ? 8'd16 : status[2] ? 8'd4 : 8'd3; 70 | assign HDMI_ARY = status[1] ? 8'd9 : status[2] ? 8'd3 : 8'd4; 71 | 72 | `include "build_id.v" 73 | localparam CONF_STR = { 74 | "A.DIGDUG;;", 75 | 76 | "O1,Aspect Ratio,Original,Wide;", 77 | "O2,Orientation,Vert,Horz;", 78 | "O35,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", 79 | "-;", 80 | "O89,Difficulty,Medium,Hardest,Easy,Hard;", 81 | "OAB,Life,3,5,1,2;", 82 | "OCE,Bonus Life,M3,M4,M5,M6,M7,Nothing,M1,M2;", 83 | "OF,Allow Continue,No,Yes;", 84 | "OG,Demo Sound,Off,On;", 85 | "-;", 86 | "OH,Service Mode,Off,On;", 87 | "-;", 88 | "R0,Reset;", 89 | "J1,Pump,Start 1P,Start 2P,Coin;", 90 | "V,v",`BUILD_DATE 91 | }; 92 | 93 | 94 | //////////////////// CLOCKS /////////////////// 95 | 96 | wire clk_hdmi; 97 | wire clk_48M; 98 | wire clk_sys = clk_hdmi; 99 | 100 | pll pll 101 | ( 102 | .rst(0), 103 | .refclk(CLK_50M), 104 | .outclk_0(clk_48M), 105 | .outclk_1(clk_hdmi) 106 | ); 107 | 108 | /////////////////////////////////////////////////// 109 | 110 | wire [31:0] status; 111 | wire [1:0] buttons; 112 | wire forced_scandoubler; 113 | 114 | wire ioctl_download; 115 | wire ioctl_wr; 116 | wire [24:0] ioctl_addr; 117 | wire [7:0] ioctl_dout; 118 | 119 | wire [10:0] ps2_key; 120 | wire [15:0] joystk1, joystk2; 121 | 122 | hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io 123 | ( 124 | .clk_sys(clk_sys), 125 | .HPS_BUS(HPS_BUS), 126 | 127 | .conf_str(CONF_STR), 128 | 129 | .buttons(buttons), 130 | .status(status), 131 | .forced_scandoubler(forced_scandoubler), 132 | 133 | .ioctl_download(ioctl_download), 134 | .ioctl_wr(ioctl_wr), 135 | .ioctl_addr(ioctl_addr), 136 | .ioctl_dout(ioctl_dout), 137 | 138 | .joystick_0(joystk1), 139 | .joystick_1(joystk2), 140 | .ps2_key(ps2_key) 141 | ); 142 | 143 | wire pressed = ps2_key[9]; 144 | wire [8:0] code = ps2_key[8:0]; 145 | always @(posedge clk_sys) begin 146 | reg old_state; 147 | old_state <= ps2_key[10]; 148 | 149 | if(old_state != ps2_key[10]) begin 150 | casex(code) 151 | 'hX75: btn_up <= pressed; // up 152 | 'hX72: btn_down <= pressed; // down 153 | 'hX6B: btn_left <= pressed; // left 154 | 'hX74: btn_right <= pressed; // right 155 | 'h029: btn_fire <= pressed; // space 156 | 'h014: btn_fire <= pressed; // ctrl 157 | 'h005: btn_one_player <= pressed; // F1 158 | 'h006: btn_two_players <= pressed; // F2 159 | 160 | // JPAC/IPAC/MAME Style Codes 161 | 'h016: btn_start_1 <= pressed; // 1 162 | 'h01E: btn_start_2 <= pressed; // 2 163 | 'h02E: btn_coin_1 <= pressed; // 5 164 | 'h036: btn_coin_2 <= pressed; // 6 165 | 'h02D: btn_up_2 <= pressed; // R 166 | 'h02B: btn_down_2 <= pressed; // F 167 | 'h023: btn_left_2 <= pressed; // D 168 | 'h034: btn_right_2 <= pressed; // G 169 | 'h01C: btn_fire_2 <= pressed; // A 170 | 'h01B: btn_fire_2 <= pressed; // S 171 | endcase 172 | end 173 | end 174 | 175 | reg btn_up = 0; 176 | reg btn_down = 0; 177 | reg btn_right = 0; 178 | reg btn_left = 0; 179 | reg btn_fire = 0; 180 | reg btn_one_player = 0; 181 | reg btn_two_players = 0; 182 | 183 | reg btn_start_1 = 0; 184 | reg btn_start_2 = 0; 185 | reg btn_coin_1 = 0; 186 | reg btn_coin_2 = 0; 187 | reg btn_up_2 = 0; 188 | reg btn_down_2 = 0; 189 | reg btn_left_2 = 0; 190 | reg btn_right_2 = 0; 191 | reg btn_fire_2 = 0; 192 | 193 | 194 | wire bCabinet = 1'b0; // (upright only) 195 | 196 | wire m_up2 = btn_up_2 | joystk2[3]; 197 | wire m_down2 = btn_down_2 | joystk2[2]; 198 | wire m_left2 = btn_left_2 | joystk2[1]; 199 | wire m_right2 = btn_right_2 | joystk2[0]; 200 | wire m_trig2 = btn_fire_2 | joystk2[4]; 201 | 202 | wire m_start1 = btn_one_player | joystk1[5] | joystk2[5] | btn_start_1; 203 | wire m_start2 = btn_two_players | joystk1[6] | joystk2[6] | btn_start_2; 204 | 205 | wire m_up1 = btn_up | joystk1[3] | (bCabinet ? 1'b0 : m_up2); 206 | wire m_down1 = btn_down | joystk1[2] | (bCabinet ? 1'b0 : m_down2); 207 | wire m_left1 = btn_left | joystk1[1] | (bCabinet ? 1'b0 : m_left2); 208 | wire m_right1 = btn_right | joystk1[0] | (bCabinet ? 1'b0 : m_right2); 209 | wire m_trig1 = btn_fire | joystk1[4] | (bCabinet ? 1'b0 : m_trig2); 210 | 211 | wire m_coin1 = btn_one_player | btn_coin_1 | joystk1[7]; 212 | wire m_coin2 = btn_two_players| btn_coin_2 | joystk2[7]; 213 | 214 | 215 | /////////////////////////////////////////////////// 216 | 217 | wire hblank, vblank; 218 | wire ce_vid; 219 | wire hs, vs; 220 | wire [3:0] r,g,b; 221 | 222 | reg ce_pix; 223 | always @(posedge clk_hdmi) begin 224 | reg old_clk; 225 | old_clk <= ce_vid; 226 | ce_pix <= old_clk & ~ce_vid; 227 | end 228 | 229 | arcade_rotate_fx #(288,224,12) arcade_video 230 | ( 231 | .*, 232 | 233 | .clk_video(clk_hdmi), 234 | 235 | .RGB_in({r,g,b}), 236 | .HBlank(hblank), 237 | .VBlank(vblank), 238 | .HSync(~hs), 239 | .VSync(~vs), 240 | 241 | .fx(status[5:3]), 242 | .no_rotate(status[2]) 243 | ); 244 | 245 | wire PCLK; 246 | wire [8:0] HPOS,VPOS; 247 | wire [11:0] POUT; 248 | HVGEN hvgen 249 | ( 250 | .HPOS(HPOS),.VPOS(VPOS),.PCLK(PCLK),.iRGB(POUT), 251 | .oRGB({b,g,r}),.HBLK(hblank),.VBLK(vblank),.HSYN(hs),.VSYN(vs) 252 | ); 253 | assign ce_vid = PCLK; 254 | 255 | 256 | wire [15:0] AOUT; 257 | assign AUDIO_L = AOUT; 258 | assign AUDIO_R = AUDIO_L; 259 | assign AUDIO_S = 0; // unsigned PCM 260 | 261 | 262 | /////////////////////////////////////////////////// 263 | 264 | wire iRST = RESET | status[0] | buttons[1] | ioctl_download; 265 | 266 | wire [1:0] COIA = 2'b00; // 1coin/1credit 267 | wire [2:0] COIB = 3'b001; // 1coin/1credit 268 | wire CABI = ~bCabinet; 269 | wire FRZE = 1'b1; 270 | 271 | wire [1:0] DIFC = status[9:8]+2'h2; 272 | wire [1:0] LIFE = status[11:10]+2'h2; 273 | wire [2:0] EXMD = status[14:12]+3'h3; 274 | wire CONT = ~status[15]; 275 | wire DSND = ~status[16]; 276 | wire SERVICE = status[17]; 277 | 278 | wire [7:0] DSW0 = {LIFE,EXMD,COIB}; 279 | wire [7:0] DSW1 = {COIA,FRZE,DSND,CONT,CABI,DIFC}; 280 | wire [7:0] INP0 = {SERVICE, 1'b0, m_coin2, m_coin1, m_start2, m_start1, m_trig2, m_trig1 }; 281 | wire [7:0] INP1 = {m_left2, m_down2, m_right2, m_up2, m_left1, m_down1, m_right1, m_up1 }; 282 | 283 | wire [7:0] oPIX; 284 | wire [7:0] oSND; 285 | 286 | FPGA_DIGDUG GameCore ( 287 | .RESET(iRST),.MCLK(clk_48M), 288 | .INP0(INP0),.INP1(INP1),.DSW0(DSW0),.DSW1(DSW1), 289 | .PH(HPOS),.PV(VPOS),.PCLK(PCLK),.POUT(oPIX), 290 | .SOUT(oSND), 291 | 292 | .ROMCL(clk_sys),.ROMAD(ioctl_addr),.ROMDT(ioctl_dout),.ROMEN(ioctl_wr) 293 | ); 294 | 295 | assign POUT = {oPIX[7:6],2'b00,oPIX[5:3],1'b0,oPIX[2:0],1'b0}; 296 | assign AOUT = {oSND,8'h0}; 297 | 298 | endmodule 299 | 300 | 301 | module HVGEN 302 | ( 303 | output [8:0] HPOS, 304 | output [8:0] VPOS, 305 | input PCLK, 306 | input [11:0] iRGB, 307 | 308 | output reg [11:0] oRGB, 309 | output reg HBLK = 1, 310 | output reg VBLK = 1, 311 | output reg HSYN = 1, 312 | output reg VSYN = 1 313 | ); 314 | 315 | reg [8:0] hcnt = 0; 316 | reg [8:0] vcnt = 0; 317 | 318 | assign HPOS = hcnt; 319 | assign VPOS = vcnt; 320 | 321 | always @(posedge PCLK) begin 322 | case (hcnt) 323 | 288: begin HBLK <= 1; hcnt <= hcnt+1; end 324 | 311: begin HSYN <= 0; hcnt <= hcnt+1; end 325 | 342: begin HSYN <= 1; hcnt <= 471; end 326 | 511: begin HBLK <= 0; hcnt <= 0; 327 | case (vcnt) 328 | 223: begin VBLK <= 1; vcnt <= vcnt+1; end 329 | 226: begin VSYN <= 0; vcnt <= vcnt+1; end 330 | 233: begin VSYN <= 1; vcnt <= 483; end 331 | 511: begin VBLK <= 0; vcnt <= 0; end 332 | default: vcnt <= vcnt+1; 333 | endcase 334 | end 335 | default: hcnt <= hcnt+1; 336 | endcase 337 | oRGB <= (HBLK|VBLK) ? 12'h0 : iRGB; 338 | end 339 | 340 | endmodule 341 | 342 | -------------------------------------------------------------------------------- /src/LINEBUF.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %RAM: 2-PORT% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: altsyncram 5 | 6 | // ============================================================ 7 | // File Name: LINEBUF.v 8 | // Megafunction Name(s): 9 | // altsyncram 10 | // 11 | // Simulation Library Files(s): 12 | // altera_mf 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 17.1.0 Build 590 10/25/2017 SJ Lite Edition 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 2017 Intel Corporation. All rights reserved. 22 | //Your use of Intel Corporation's design tools, logic functions 23 | //and other software and tools, and its AMPP partner logic 24 | //functions, and any output files from any of the foregoing 25 | //(including device programming or simulation files), and any 26 | //associated documentation or information are expressly subject 27 | //to the terms and conditions of the Intel Program License 28 | //Subscription Agreement, the Intel Quartus Prime License Agreement, 29 | //the Intel FPGA IP License Agreement, or other applicable license 30 | //agreement, including, without limitation, that your use is for 31 | //the sole purpose of programming logic devices manufactured by 32 | //Intel and sold by Intel or its authorized distributors. Please 33 | //refer to the applicable agreement for further details. 34 | 35 | 36 | // synopsys translate_off 37 | `timescale 1 ps / 1 ps 38 | // synopsys translate_on 39 | module LINEBUF ( 40 | address_a, 41 | address_b, 42 | clock_a, 43 | clock_b, 44 | data_a, 45 | data_b, 46 | wren_a, 47 | wren_b, 48 | q_a, 49 | q_b); 50 | 51 | input [9:0] address_a; 52 | input [9:0] address_b; 53 | input clock_a; 54 | input clock_b; 55 | input [7:0] data_a; 56 | input [7:0] data_b; 57 | input wren_a; 58 | input wren_b; 59 | output [7:0] q_a; 60 | output [7:0] q_b; 61 | `ifndef ALTERA_RESERVED_QIS 62 | // synopsys translate_off 63 | `endif 64 | tri1 clock_a; 65 | tri0 wren_a; 66 | tri0 wren_b; 67 | `ifndef ALTERA_RESERVED_QIS 68 | // synopsys translate_on 69 | `endif 70 | 71 | wire [7:0] sub_wire0; 72 | wire [7:0] sub_wire1; 73 | wire [7:0] q_a = sub_wire0[7:0]; 74 | wire [7:0] q_b = sub_wire1[7:0]; 75 | 76 | altsyncram altsyncram_component ( 77 | .address_a (address_a), 78 | .address_b (address_b), 79 | .clock0 (clock_a), 80 | .clock1 (clock_b), 81 | .data_a (data_a), 82 | .data_b (data_b), 83 | .wren_a (wren_a), 84 | .wren_b (wren_b), 85 | .q_a (sub_wire0), 86 | .q_b (sub_wire1), 87 | .aclr0 (1'b0), 88 | .aclr1 (1'b0), 89 | .addressstall_a (1'b0), 90 | .addressstall_b (1'b0), 91 | .byteena_a (1'b1), 92 | .byteena_b (1'b1), 93 | .clocken0 (1'b1), 94 | .clocken1 (1'b1), 95 | .clocken2 (1'b1), 96 | .clocken3 (1'b1), 97 | .eccstatus (), 98 | .rden_a (1'b1), 99 | .rden_b (1'b1)); 100 | defparam 101 | altsyncram_component.address_reg_b = "CLOCK1", 102 | altsyncram_component.clock_enable_input_a = "BYPASS", 103 | altsyncram_component.clock_enable_input_b = "BYPASS", 104 | altsyncram_component.clock_enable_output_a = "BYPASS", 105 | altsyncram_component.clock_enable_output_b = "BYPASS", 106 | altsyncram_component.indata_reg_b = "CLOCK1", 107 | altsyncram_component.intended_device_family = "Cyclone V", 108 | altsyncram_component.lpm_type = "altsyncram", 109 | altsyncram_component.numwords_a = 1024, 110 | altsyncram_component.numwords_b = 1024, 111 | altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", 112 | altsyncram_component.outdata_aclr_a = "NONE", 113 | altsyncram_component.outdata_aclr_b = "NONE", 114 | altsyncram_component.outdata_reg_a = "UNREGISTERED", 115 | altsyncram_component.outdata_reg_b = "UNREGISTERED", 116 | altsyncram_component.power_up_uninitialized = "FALSE", 117 | altsyncram_component.ram_block_type = "M10K", 118 | altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", 119 | altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", 120 | altsyncram_component.widthad_a = 10, 121 | altsyncram_component.widthad_b = 10, 122 | altsyncram_component.width_a = 8, 123 | altsyncram_component.width_b = 8, 124 | altsyncram_component.width_byteena_a = 1, 125 | altsyncram_component.width_byteena_b = 1, 126 | altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1"; 127 | 128 | 129 | endmodule 130 | 131 | // ============================================================ 132 | // CNX file retrieval info 133 | // ============================================================ 134 | // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 135 | // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" 136 | // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" 137 | // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" 138 | // Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" 139 | // Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" 140 | // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" 141 | // Retrieval info: PRIVATE: BlankMemory NUMERIC "1" 142 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 143 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" 144 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 145 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" 146 | // Retrieval info: PRIVATE: CLRdata NUMERIC "0" 147 | // Retrieval info: PRIVATE: CLRq NUMERIC "0" 148 | // Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" 149 | // Retrieval info: PRIVATE: CLRrren NUMERIC "0" 150 | // Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" 151 | // Retrieval info: PRIVATE: CLRwren NUMERIC "0" 152 | // Retrieval info: PRIVATE: Clock NUMERIC "5" 153 | // Retrieval info: PRIVATE: Clock_A NUMERIC "0" 154 | // Retrieval info: PRIVATE: Clock_B NUMERIC "0" 155 | // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 156 | // Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" 157 | // Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" 158 | // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" 159 | // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 160 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 161 | // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 162 | // Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 163 | // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 164 | // Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" 165 | // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" 166 | // Retrieval info: PRIVATE: MIFfilename STRING "" 167 | // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" 168 | // Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" 169 | // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" 170 | // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2" 171 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" 172 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" 173 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" 174 | // Retrieval info: PRIVATE: REGdata NUMERIC "1" 175 | // Retrieval info: PRIVATE: REGq NUMERIC "0" 176 | // Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" 177 | // Retrieval info: PRIVATE: REGrren NUMERIC "0" 178 | // Retrieval info: PRIVATE: REGwraddress NUMERIC "1" 179 | // Retrieval info: PRIVATE: REGwren NUMERIC "1" 180 | // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 181 | // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" 182 | // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" 183 | // Retrieval info: PRIVATE: VarWidth NUMERIC "0" 184 | // Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8" 185 | // Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8" 186 | // Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8" 187 | // Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8" 188 | // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" 189 | // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" 190 | // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" 191 | // Retrieval info: PRIVATE: enable NUMERIC "0" 192 | // Retrieval info: PRIVATE: rden NUMERIC "0" 193 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 194 | // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" 195 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 196 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" 197 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" 198 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" 199 | // Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" 200 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone V" 201 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 202 | // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1024" 203 | // Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "1024" 204 | // Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" 205 | // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" 206 | // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" 207 | // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" 208 | // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" 209 | // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" 210 | // Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M10K" 211 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" 212 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ" 213 | // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "10" 214 | // Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "10" 215 | // Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" 216 | // Retrieval info: CONSTANT: WIDTH_B NUMERIC "8" 217 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" 218 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" 219 | // Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" 220 | // Retrieval info: USED_PORT: address_a 0 0 10 0 INPUT NODEFVAL "address_a[9..0]" 221 | // Retrieval info: USED_PORT: address_b 0 0 10 0 INPUT NODEFVAL "address_b[9..0]" 222 | // Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT VCC "clock_a" 223 | // Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL "clock_b" 224 | // Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..0]" 225 | // Retrieval info: USED_PORT: data_b 0 0 8 0 INPUT NODEFVAL "data_b[7..0]" 226 | // Retrieval info: USED_PORT: q_a 0 0 8 0 OUTPUT NODEFVAL "q_a[7..0]" 227 | // Retrieval info: USED_PORT: q_b 0 0 8 0 OUTPUT NODEFVAL "q_b[7..0]" 228 | // Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a" 229 | // Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b" 230 | // Retrieval info: CONNECT: @address_a 0 0 10 0 address_a 0 0 10 0 231 | // Retrieval info: CONNECT: @address_b 0 0 10 0 address_b 0 0 10 0 232 | // Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 233 | // Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 234 | // Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0 235 | // Retrieval info: CONNECT: @data_b 0 0 8 0 data_b 0 0 8 0 236 | // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 237 | // Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 238 | // Retrieval info: CONNECT: q_a 0 0 8 0 @q_a 0 0 8 0 239 | // Retrieval info: CONNECT: q_b 0 0 8 0 @q_b 0 0 8 0 240 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF.v TRUE 241 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF.inc FALSE 242 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF.cmp FALSE 243 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF.bsf FALSE 244 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF_inst.v FALSE 245 | // Retrieval info: GEN_FILE: TYPE_NORMAL LINEBUF_bb.v FALSE 246 | // Retrieval info: LIB_FILE: altera_mf 247 | -------------------------------------------------------------------------------- /sys/pll_hdmi_adj.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- HDMI PLL Adjust 3 | -------------------------------------------------------------------------------- 4 | 5 | -- Changes the HDMI PLL frequency according to the scaler suggestions. 6 | -------------------------------------------- 7 | -- LLTUNE : 8 | -- 0 : Input Syncline 9 | -- 1 : 10 | -- 2 : Input Interlaced mode 11 | -- 3 : Input Interlaced field 12 | -- 4 : Output Syncline 13 | -- 5 : 14 | -- 6 : Input clock 15 | -- 7 : Output clock 16 | 17 | LIBRARY ieee; 18 | USE ieee.std_logic_1164.ALL; 19 | USE ieee.numeric_std.ALL; 20 | 21 | ENTITY pll_hdmi_adj IS 22 | PORT ( 23 | -- Scaler 24 | llena : IN std_logic; -- 0=Disabled 1=Enabled 25 | lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler 26 | 27 | locked : OUT std_logic; 28 | 29 | -- Signals from reconfig commands 30 | i_waitrequest : OUT std_logic; 31 | i_write : IN std_logic; 32 | i_address : IN unsigned(5 DOWNTO 0); 33 | i_writedata : IN unsigned(31 DOWNTO 0); 34 | 35 | -- Outputs to PLL_HDMI_CFG 36 | o_waitrequest : IN std_logic; 37 | o_write : OUT std_logic; 38 | o_address : OUT unsigned(5 DOWNTO 0); 39 | o_writedata : OUT unsigned(31 DOWNTO 0); 40 | 41 | ------------------------------------ 42 | clk : IN std_logic; 43 | reset_na : IN std_logic 44 | ); 45 | 46 | BEGIN 47 | 48 | 49 | END ENTITY pll_hdmi_adj; 50 | 51 | --############################################################################## 52 | 53 | ARCHITECTURE rtl OF pll_hdmi_adj IS 54 | SIGNAL pwrite : std_logic; 55 | SIGNAL paddress : unsigned(5 DOWNTO 0); 56 | SIGNAL pdata : unsigned(31 DOWNTO 0); 57 | TYPE enum_state IS (sIDLE,sW1,sW2,sW3,sW4,sW5,sW6); 58 | SIGNAL state : enum_state; 59 | SIGNAL tune_freq,tune_phase : unsigned(5 DOWNTO 0); 60 | SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); 61 | SIGNAL mfrac,mfrac_mem,mfrac_ref,diff : unsigned(40 DOWNTO 0); 62 | SIGNAL mul : unsigned(15 DOWNTO 0); 63 | SIGNAL sign,sign_pre : std_logic; 64 | SIGNAL up,modo,phm,dir : std_logic; 65 | SIGNAL cpt : natural RANGE 0 TO 3; 66 | SIGNAL col : natural RANGE 0 TO 15; 67 | 68 | SIGNAL icpt,ocpt,ssh : natural RANGE 0 TO 2**24-1; 69 | SIGNAL isync,isync2,itog,ipulse : std_logic; 70 | SIGNAL osync,osync2,otog,opulse : std_logic; 71 | SIGNAL sync,pulse,los,lop : std_logic; 72 | SIGNAL osize,isize,offset,osizep : signed(23 DOWNTO 0); 73 | SIGNAL logcpt : natural RANGE 0 TO 31; 74 | SIGNAL udiff : integer RANGE -2**23 TO 2**23-1 :=0; 75 | 76 | BEGIN 77 | ---------------------------------------------------------------------------- 78 | -- Sample image sizes 79 | Sampler:PROCESS(clk,reset_na) IS 80 | BEGIN 81 | IF reset_na='0' THEN 82 | --pragma synthesis_off 83 | otog<='0'; 84 | itog<='0'; 85 | isync<='0'; 86 | isync2<='0'; 87 | osync<='0'; 88 | osync2<='0'; 89 | --pragma synthesis_on 90 | 91 | ELSIF rising_edge(clk) THEN 92 | -- Clock domain crossing 93 | isync<=lltune(0); -- 94 | isync2<=isync; 95 | osync<=lltune(4); -- 96 | osync2<=osync; 97 | 98 | itog<=itog XOR (isync AND NOT isync2); 99 | otog<=otog XOR (osync AND NOT osync2); 100 | 101 | --ipulse<=isync AND NOT isync2 AND itog; 102 | --opulse<=osync AND NOT osync2 AND otog; 103 | 104 | -- Measure output image size 105 | IF osync='1' AND osync2='0' AND otog='1' THEN 106 | ocpt<=0; 107 | osizep<=to_signed(ocpt,24); 108 | ELSE 109 | ocpt<=ocpt+1; 110 | END IF; 111 | 112 | -- Measure input image size 113 | IF isync='1' AND isync2='0' AND itog='1' THEN 114 | icpt<=0; 115 | --isize<=to_signed(icpt,24); 116 | osize<=osizep; 117 | offset<=to_signed(ocpt,24); 118 | udiff<=integer(to_integer(osizep)) - integer(icpt); 119 | sync<='1'; 120 | ELSE 121 | icpt<=icpt+1; 122 | sync<='0'; 123 | END IF; 124 | 125 | -------------------------------------------- 126 | pulse<='0'; 127 | IF sync='1' THEN 128 | logcpt<=0; 129 | ssh<=to_integer(osize); 130 | los<='0'; 131 | lop<='0'; 132 | 133 | ELSIF logcpt<24 THEN 134 | -- Frequency difference 135 | IF udiff>0 AND ssh=osize/2 AND ssh<(osize-offset) AND lop='0' THEN 147 | tune_phase<='1' & to_unsigned(logcpt,5); 148 | lop<='1'; 149 | END IF; 150 | ssh<=ssh/2; 151 | logcpt<=logcpt+1; 152 | 153 | ELSIF logcpt=24 THEN 154 | pulse<='1'; 155 | ssh<=ssh/2; 156 | logcpt<=logcpt+1; 157 | END IF; 158 | 159 | END IF; 160 | END PROCESS Sampler; 161 | 162 | ---------------------------------------------------------------------------- 163 | -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. 164 | -- 000100 : M counter 165 | -- 000111 : M counter Fractional Value K 166 | 167 | Comb:PROCESS(i_write,i_address, 168 | i_writedata,pwrite,paddress,pdata) IS 169 | BEGIN 170 | IF i_write='1' THEN 171 | o_write <=i_write; 172 | o_address <=i_address; 173 | o_writedata <=i_writedata; 174 | ELSE 175 | o_write <=pwrite; 176 | o_address <=paddress; 177 | o_writedata<=pdata; 178 | END IF; 179 | END PROCESS Comb; 180 | 181 | i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0'; 182 | 183 | ---------------------------------------------------------------------------- 184 | Schmurtz:PROCESS(clk,reset_na) IS 185 | VARIABLE off_v,ofp_v : natural RANGE 0 TO 63; 186 | VARIABLE diff_v : unsigned(40 DOWNTO 0); 187 | VARIABLE mulco : unsigned(15 DOWNTO 0); 188 | VARIABLE up_v,sign_v : std_logic; 189 | BEGIN 190 | IF reset_na='0' THEN 191 | modo<='0'; 192 | state<=sIDLE; 193 | ELSIF rising_edge(clk) THEN 194 | ------------------------------------------------------ 195 | -- Snoop accesses to PLL reconfiguration 196 | IF i_address="000100" AND i_write='1' THEN 197 | mfrac (40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + 198 | ('0' & i_writedata(7 DOWNTO 0)); 199 | mfrac_ref(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + 200 | ('0' & i_writedata(7 DOWNTO 0)); 201 | mfrac_mem(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + 202 | ('0' & i_writedata(7 DOWNTO 0)); 203 | mul<=i_writedata(15 DOWNTO 0); 204 | modo<='1'; 205 | END IF; 206 | 207 | IF i_address="000111" AND i_write='1' THEN 208 | mfrac (31 DOWNTO 0)<=i_writedata; 209 | mfrac_ref(31 DOWNTO 0)<=i_writedata; 210 | mfrac_mem(31 DOWNTO 0)<=i_writedata; 211 | modo<='1'; 212 | END IF; 213 | 214 | ------------------------------------------------------ 215 | -- Tuning 216 | off_v:=to_integer('0' & tune_freq(4 DOWNTO 0)); 217 | ofp_v:=to_integer('0' & tune_phase(4 DOWNTO 0)); 218 | --IF off_v<8 THEN off_v:=8; END IF; 219 | --IF ofp_v<7 THEN ofp_v:=7; END IF; 220 | IF off_v<4 THEN off_v:=4; END IF; 221 | IF ofp_v<4 THEN ofp_v:=4; END IF; 222 | 223 | IF off_v>=18 AND ofp_v>=18 THEN 224 | locked<=llena; 225 | ELSE 226 | locked<='0'; 227 | END IF; 228 | 229 | up_v:='0'; 230 | IF pulse='1' THEN 231 | cpt<=(cpt+1) MOD 4; 232 | IF llena='0' THEN 233 | -- Recover original freq when disabling low lag mode 234 | cpt<=0; 235 | col<=0; 236 | IF modo='1' THEN 237 | mfrac<=mfrac_mem; 238 | mfrac_ref<=mfrac_mem; 239 | up<='1'; 240 | modo<='0'; 241 | END IF; 242 | 243 | ELSIF phm='0' AND cpt=0 THEN 244 | -- Frequency adjust 245 | sign_v:=tune_freq(5); 246 | IF col<10 THEN col<=col+1; END IF; 247 | IF off_v>=16 AND col>=10 THEN 248 | phm<='1'; 249 | col<=0; 250 | ELSE 251 | off_v:=off_v+1; 252 | IF off_v>17 THEN 253 | off_v:=off_v + 3; 254 | END IF; 255 | up_v:='1'; 256 | up<='1'; 257 | END IF; 258 | 259 | ELSIF cpt=0 THEN 260 | -- Phase adjust 261 | sign_v:=NOT tune_phase(5); 262 | col<=col+1; 263 | IF col>=10 THEN 264 | phm<='0'; 265 | up_v:='1'; 266 | off_v:=31; 267 | col<=0; 268 | ELSE 269 | off_v:=ofp_v + 1; 270 | IF ofp_v>7 THEN 271 | off_v:=off_v + 1; 272 | END IF; 273 | IF ofp_v>14 THEN 274 | off_v:=off_v + 2; 275 | END IF; 276 | IF ofp_v>17 THEN 277 | off_v:=off_v + 3; 278 | END IF; 279 | up_v:='1'; 280 | END IF; 281 | up<='1'; 282 | END IF; 283 | END IF; 284 | 285 | diff_v:=shift_right(mfrac_ref,off_v); 286 | IF sign_v='0' THEN 287 | diff_v:=mfrac_ref + diff_v; 288 | ELSE 289 | diff_v:=mfrac_ref - diff_v; 290 | END IF; 291 | 292 | IF up_v='1' THEN 293 | mfrac<=diff_v; 294 | END IF; 295 | 296 | IF up_v='1' AND phm='0' THEN 297 | mfrac_ref<=diff_v; 298 | END IF; 299 | 300 | ------------------------------------------------------ 301 | -- Update PLL registers 302 | mulco:=mfrac(40 DOWNTO 33) & (mfrac(40 DOWNTO 33) + ('0' & mfrac(32))); 303 | 304 | CASE state IS 305 | WHEN sIDLE => 306 | pwrite<='0'; 307 | IF up='1' THEN 308 | up<='0'; 309 | IF mulco/=mul THEN 310 | state<=sW1; 311 | ELSE 312 | state<=sW3; 313 | END IF; 314 | END IF; 315 | 316 | WHEN sW1 => -- Change M multiplier 317 | mul<=mulco; 318 | pdata<=x"0000" & mulco; 319 | paddress<="000100"; 320 | pwrite<='1'; 321 | state<=sW2; 322 | 323 | WHEN sW2 => 324 | IF pwrite='1' AND o_waitrequest='0' THEN 325 | state<=sW3; 326 | pwrite<='0'; 327 | END IF; 328 | 329 | WHEN sW3 => -- Change M fractional value 330 | pdata<=mfrac(31 DOWNTO 0); 331 | paddress<="000111"; 332 | pwrite<='1'; 333 | state<=sW4; 334 | 335 | WHEN sW4 => 336 | IF pwrite='1' AND o_waitrequest='0' THEN 337 | state<=sW5; 338 | pwrite<='0'; 339 | END IF; 340 | 341 | WHEN sW5 => 342 | pdata<=x"0000_0001"; 343 | paddress<="000010"; 344 | pwrite<='1'; 345 | state<=sW6; 346 | 347 | WHEN sW6 => 348 | IF pwrite='1' AND o_waitrequest='0' THEN 349 | pwrite<='0'; 350 | state<=sIDLE; 351 | END IF; 352 | END CASE; 353 | 354 | END IF; 355 | END PROCESS Schmurtz; 356 | 357 | ---------------------------------------------------------------------------- 358 | 359 | END ARCHITECTURE rtl; 360 | 361 | -------------------------------------------------------------------------------- /sys/sysmem.sv: -------------------------------------------------------------------------------- 1 | `timescale 1 ps / 1 ps 2 | module sysmem_lite 3 | ( 4 | output clock, 5 | output reset_out, 6 | 7 | input reset_hps_cold_req, 8 | input reset_hps_warm_req, 9 | input reset_core_req, 10 | 11 | input ram1_clk, 12 | input [28:0] ram1_address, 13 | input [7:0] ram1_burstcount, 14 | output ram1_waitrequest, 15 | output [63:0] ram1_readdata, 16 | output ram1_readdatavalid, 17 | input ram1_read, 18 | input [63:0] ram1_writedata, 19 | input [7:0] ram1_byteenable, 20 | input ram1_write, 21 | 22 | input ram2_clk, 23 | input [28:0] ram2_address, 24 | input [7:0] ram2_burstcount, 25 | output ram2_waitrequest, 26 | output [63:0] ram2_readdata, 27 | output ram2_readdatavalid, 28 | input ram2_read, 29 | input [63:0] ram2_writedata, 30 | input [7:0] ram2_byteenable, 31 | input ram2_write, 32 | 33 | input vbuf_clk, 34 | input [27:0] vbuf_address, 35 | input [7:0] vbuf_burstcount, 36 | output vbuf_waitrequest, 37 | output [127:0] vbuf_readdata, 38 | output vbuf_readdatavalid, 39 | input vbuf_read, 40 | input [127:0] vbuf_writedata, 41 | input [15:0] vbuf_byteenable, 42 | input vbuf_write 43 | ); 44 | 45 | assign reset_out = ~init_reset_n | ~hps_h2f_reset_n | reset_core_req; 46 | 47 | sysmem_HPS_fpga_interfaces fpga_interfaces ( 48 | .f2h_cold_rst_req_n (~reset_hps_cold_req), 49 | .f2h_warm_rst_req_n (~reset_hps_warm_req), 50 | .h2f_user0_clk (clock), 51 | .h2f_rst_n (hps_h2f_reset_n), 52 | .f2h_sdram0_clk (vbuf_clk), 53 | .f2h_sdram0_ADDRESS (vbuf_address), 54 | .f2h_sdram0_BURSTCOUNT (vbuf_burstcount), 55 | .f2h_sdram0_WAITREQUEST (vbuf_waitrequest), 56 | .f2h_sdram0_READDATA (vbuf_readdata), 57 | .f2h_sdram0_READDATAVALID (vbuf_readdatavalid), 58 | .f2h_sdram0_READ (vbuf_read), 59 | .f2h_sdram0_WRITEDATA (vbuf_writedata), 60 | .f2h_sdram0_BYTEENABLE (vbuf_byteenable), 61 | .f2h_sdram0_WRITE (vbuf_write), 62 | .f2h_sdram1_clk (ram1_clk), 63 | .f2h_sdram1_ADDRESS (ram1_address), 64 | .f2h_sdram1_BURSTCOUNT (ram1_burstcount), 65 | .f2h_sdram1_WAITREQUEST (ram1_waitrequest), 66 | .f2h_sdram1_READDATA (ram1_readdata), 67 | .f2h_sdram1_READDATAVALID (ram1_readdatavalid), 68 | .f2h_sdram1_READ (ram1_read), 69 | .f2h_sdram1_WRITEDATA (ram1_writedata), 70 | .f2h_sdram1_BYTEENABLE (ram1_byteenable), 71 | .f2h_sdram1_WRITE (ram1_write), 72 | .f2h_sdram2_clk (ram2_clk), 73 | .f2h_sdram2_ADDRESS (ram2_address), 74 | .f2h_sdram2_BURSTCOUNT (ram2_burstcount), 75 | .f2h_sdram2_WAITREQUEST (ram2_waitrequest), 76 | .f2h_sdram2_READDATA (ram2_readdata), 77 | .f2h_sdram2_READDATAVALID (ram2_readdatavalid), 78 | .f2h_sdram2_READ (ram2_read), 79 | .f2h_sdram2_WRITEDATA (ram2_writedata), 80 | .f2h_sdram2_BYTEENABLE (ram2_byteenable), 81 | .f2h_sdram2_WRITE (ram2_write) 82 | ); 83 | 84 | wire hps_h2f_reset_n; 85 | 86 | reg init_reset_n = 0; 87 | always @(posedge clock) begin 88 | integer timeout = 0; 89 | 90 | if(timeout < 2000000) begin 91 | init_reset_n <= 0; 92 | timeout <= timeout + 1; 93 | end 94 | else init_reset_n <= 1; 95 | end 96 | 97 | endmodule 98 | 99 | 100 | module sysmem_HPS_fpga_interfaces 101 | ( 102 | // h2f_reset 103 | output wire [1 - 1 : 0 ] h2f_rst_n 104 | 105 | // f2h_cold_reset_req 106 | ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n 107 | 108 | // f2h_warm_reset_req 109 | ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n 110 | 111 | // h2f_user0_clock 112 | ,output wire [1 - 1 : 0 ] h2f_user0_clk 113 | 114 | // f2h_sdram0_data 115 | ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS 116 | ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT 117 | ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST 118 | ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA 119 | ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID 120 | ,input wire [1 - 1 : 0 ] f2h_sdram0_READ 121 | ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA 122 | ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE 123 | ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE 124 | 125 | // f2h_sdram0_clock 126 | ,input wire [1 - 1 : 0 ] f2h_sdram0_clk 127 | 128 | // f2h_sdram1_data 129 | ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS 130 | ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT 131 | ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST 132 | ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA 133 | ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID 134 | ,input wire [1 - 1 : 0 ] f2h_sdram1_READ 135 | ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA 136 | ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE 137 | ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE 138 | 139 | // f2h_sdram1_clock 140 | ,input wire [1 - 1 : 0 ] f2h_sdram1_clk 141 | 142 | // f2h_sdram2_data 143 | ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS 144 | ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT 145 | ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST 146 | ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA 147 | ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID 148 | ,input wire [1 - 1 : 0 ] f2h_sdram2_READ 149 | ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA 150 | ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE 151 | ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE 152 | 153 | // f2h_sdram2_clock 154 | ,input wire [1 - 1 : 0 ] f2h_sdram2_clk 155 | ); 156 | 157 | 158 | wire [29 - 1 : 0] intermediate; 159 | assign intermediate[0:0] = ~intermediate[1:1]; 160 | assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; 161 | assign intermediate[2:2] = intermediate[9:9]; 162 | assign intermediate[3:3] = intermediate[9:9]; 163 | assign intermediate[5:5] = intermediate[9:9]; 164 | assign intermediate[6:6] = intermediate[9:9]; 165 | assign intermediate[10:10] = intermediate[9:9]; 166 | assign intermediate[11:11] = ~intermediate[12:12]; 167 | assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; 168 | assign intermediate[13:13] = intermediate[18:18]; 169 | assign intermediate[15:15] = intermediate[18:18]; 170 | assign intermediate[19:19] = intermediate[18:18]; 171 | assign intermediate[20:20] = ~intermediate[21:21]; 172 | assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; 173 | assign intermediate[22:22] = intermediate[27:27]; 174 | assign intermediate[24:24] = intermediate[27:27]; 175 | assign intermediate[28:28] = intermediate[27:27]; 176 | assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; 177 | assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; 178 | assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; 179 | assign intermediate[4:4] = f2h_sdram0_READ[0:0]; 180 | assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; 181 | assign intermediate[9:9] = f2h_sdram0_clk[0:0]; 182 | assign intermediate[14:14] = f2h_sdram1_READ[0:0]; 183 | assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; 184 | assign intermediate[18:18] = f2h_sdram1_clk[0:0]; 185 | assign intermediate[23:23] = f2h_sdram2_READ[0:0]; 186 | assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; 187 | assign intermediate[27:27] = f2h_sdram2_clk[0:0]; 188 | 189 | cyclonev_hps_interface_clocks_resets clocks_resets( 190 | .f2h_warm_rst_req_n({ 191 | f2h_warm_rst_req_n[0:0] // 0:0 192 | }) 193 | ,.f2h_pending_rst_ack({ 194 | 1'b1 // 0:0 195 | }) 196 | ,.f2h_dbg_rst_req_n({ 197 | 1'b1 // 0:0 198 | }) 199 | ,.h2f_rst_n({ 200 | h2f_rst_n[0:0] // 0:0 201 | }) 202 | ,.f2h_cold_rst_req_n({ 203 | f2h_cold_rst_req_n[0:0] // 0:0 204 | }) 205 | ,.h2f_user0_clk({ 206 | h2f_user0_clk[0:0] // 0:0 207 | }) 208 | ); 209 | 210 | 211 | cyclonev_hps_interface_dbg_apb debug_apb( 212 | .DBG_APB_DISABLE({ 213 | 1'b0 // 0:0 214 | }) 215 | ,.P_CLK_EN({ 216 | 1'b0 // 0:0 217 | }) 218 | ); 219 | 220 | 221 | cyclonev_hps_interface_tpiu_trace tpiu( 222 | .traceclk_ctl({ 223 | 1'b1 // 0:0 224 | }) 225 | ); 226 | 227 | 228 | cyclonev_hps_interface_boot_from_fpga boot_from_fpga( 229 | .boot_from_fpga_ready({ 230 | 1'b0 // 0:0 231 | }) 232 | ,.boot_from_fpga_on_failure({ 233 | 1'b0 // 0:0 234 | }) 235 | ,.bsel_en({ 236 | 1'b0 // 0:0 237 | }) 238 | ,.csel_en({ 239 | 1'b0 // 0:0 240 | }) 241 | ,.csel({ 242 | 2'b01 // 1:0 243 | }) 244 | ,.bsel({ 245 | 3'b001 // 2:0 246 | }) 247 | ); 248 | 249 | 250 | cyclonev_hps_interface_fpga2hps fpga2hps( 251 | .port_size_config({ 252 | 2'b11 // 1:0 253 | }) 254 | ); 255 | 256 | 257 | cyclonev_hps_interface_hps2fpga hps2fpga( 258 | .port_size_config({ 259 | 2'b11 // 1:0 260 | }) 261 | ); 262 | 263 | 264 | cyclonev_hps_interface_fpga2sdram f2sdram( 265 | .cfg_rfifo_cport_map({ 266 | 16'b0010000100000000 // 15:0 267 | }) 268 | ,.cfg_wfifo_cport_map({ 269 | 16'b0010000100000000 // 15:0 270 | }) 271 | ,.rd_ready_3({ 272 | 1'b1 // 0:0 273 | }) 274 | ,.cmd_port_clk_2({ 275 | intermediate[28:28] // 0:0 276 | }) 277 | ,.rd_ready_2({ 278 | 1'b1 // 0:0 279 | }) 280 | ,.cmd_port_clk_1({ 281 | intermediate[19:19] // 0:0 282 | }) 283 | ,.rd_ready_1({ 284 | 1'b1 // 0:0 285 | }) 286 | ,.cmd_port_clk_0({ 287 | intermediate[10:10] // 0:0 288 | }) 289 | ,.rd_ready_0({ 290 | 1'b1 // 0:0 291 | }) 292 | ,.wrack_ready_2({ 293 | 1'b1 // 0:0 294 | }) 295 | ,.wrack_ready_1({ 296 | 1'b1 // 0:0 297 | }) 298 | ,.wrack_ready_0({ 299 | 1'b1 // 0:0 300 | }) 301 | ,.cmd_ready_2({ 302 | intermediate[21:21] // 0:0 303 | }) 304 | ,.cmd_ready_1({ 305 | intermediate[12:12] // 0:0 306 | }) 307 | ,.cmd_ready_0({ 308 | intermediate[1:1] // 0:0 309 | }) 310 | ,.cfg_port_width({ 311 | 12'b000000010110 // 11:0 312 | }) 313 | ,.rd_valid_3({ 314 | f2h_sdram2_READDATAVALID[0:0] // 0:0 315 | }) 316 | ,.rd_valid_2({ 317 | f2h_sdram1_READDATAVALID[0:0] // 0:0 318 | }) 319 | ,.rd_valid_1({ 320 | f2h_sdram0_READDATAVALID[0:0] // 0:0 321 | }) 322 | ,.rd_clk_3({ 323 | intermediate[22:22] // 0:0 324 | }) 325 | ,.rd_data_3({ 326 | f2h_sdram2_READDATA[63:0] // 63:0 327 | }) 328 | ,.rd_clk_2({ 329 | intermediate[13:13] // 0:0 330 | }) 331 | ,.rd_data_2({ 332 | f2h_sdram1_READDATA[63:0] // 63:0 333 | }) 334 | ,.rd_clk_1({ 335 | intermediate[3:3] // 0:0 336 | }) 337 | ,.rd_data_1({ 338 | f2h_sdram0_READDATA[127:64] // 63:0 339 | }) 340 | ,.rd_clk_0({ 341 | intermediate[2:2] // 0:0 342 | }) 343 | ,.rd_data_0({ 344 | f2h_sdram0_READDATA[63:0] // 63:0 345 | }) 346 | ,.cfg_axi_mm_select({ 347 | 6'b000000 // 5:0 348 | }) 349 | ,.cmd_valid_2({ 350 | intermediate[26:26] // 0:0 351 | }) 352 | ,.cmd_valid_1({ 353 | intermediate[17:17] // 0:0 354 | }) 355 | ,.cmd_valid_0({ 356 | intermediate[8:8] // 0:0 357 | }) 358 | ,.cfg_cport_rfifo_map({ 359 | 18'b000000000011010000 // 17:0 360 | }) 361 | ,.wr_data_3({ 362 | 2'b00 // 89:88 363 | ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 364 | ,16'b0000000000000000 // 79:64 365 | ,f2h_sdram2_WRITEDATA[63:0] // 63:0 366 | }) 367 | ,.wr_data_2({ 368 | 2'b00 // 89:88 369 | ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 370 | ,16'b0000000000000000 // 79:64 371 | ,f2h_sdram1_WRITEDATA[63:0] // 63:0 372 | }) 373 | ,.wr_data_1({ 374 | 2'b00 // 89:88 375 | ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 376 | ,16'b0000000000000000 // 79:64 377 | ,f2h_sdram0_WRITEDATA[127:64] // 63:0 378 | }) 379 | ,.cfg_cport_type({ 380 | 12'b000000111111 // 11:0 381 | }) 382 | ,.wr_data_0({ 383 | 2'b00 // 89:88 384 | ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 385 | ,16'b0000000000000000 // 79:64 386 | ,f2h_sdram0_WRITEDATA[63:0] // 63:0 387 | }) 388 | ,.cfg_cport_wfifo_map({ 389 | 18'b000000000011010000 // 17:0 390 | }) 391 | ,.wr_clk_3({ 392 | intermediate[24:24] // 0:0 393 | }) 394 | ,.wr_clk_2({ 395 | intermediate[15:15] // 0:0 396 | }) 397 | ,.wr_clk_1({ 398 | intermediate[6:6] // 0:0 399 | }) 400 | ,.wr_clk_0({ 401 | intermediate[5:5] // 0:0 402 | }) 403 | ,.cmd_data_2({ 404 | 18'b000000000000000000 // 59:42 405 | ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 406 | ,3'b000 // 33:31 407 | ,f2h_sdram2_ADDRESS[28:0] // 30:2 408 | ,intermediate[25:25] // 1:1 409 | ,intermediate[23:23] // 0:0 410 | }) 411 | ,.cmd_data_1({ 412 | 18'b000000000000000000 // 59:42 413 | ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 414 | ,3'b000 // 33:31 415 | ,f2h_sdram1_ADDRESS[28:0] // 30:2 416 | ,intermediate[16:16] // 1:1 417 | ,intermediate[14:14] // 0:0 418 | }) 419 | ,.cmd_data_0({ 420 | 18'b000000000000000000 // 59:42 421 | ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 422 | ,4'b0000 // 33:30 423 | ,f2h_sdram0_ADDRESS[27:0] // 29:2 424 | ,intermediate[7:7] // 1:1 425 | ,intermediate[4:4] // 0:0 426 | }) 427 | ); 428 | 429 | endmodule 430 | -------------------------------------------------------------------------------- /sys/hq2x.sv: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Copyright (c) 2012-2013 Ludvig Strigeus 4 | // Copyright (c) 2017,2018 Sorgelig 5 | // 6 | // This program is GPL Licensed. See COPYING for the full license. 7 | // 8 | // 9 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | // synopsys translate_off 12 | `timescale 1 ps / 1 ps 13 | // synopsys translate_on 14 | 15 | module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) 16 | ( 17 | input clk, 18 | input ce_x4, 19 | input [DWIDTH:0] inputpixel, 20 | input mono, 21 | input disable_hq2x, 22 | input reset_frame, 23 | input reset_line, 24 | input [1:0] read_y, 25 | input hblank, 26 | output [DWIDTH:0] outpixel 27 | ); 28 | 29 | 30 | localparam AWIDTH = $clog2(LENGTH)-1; 31 | localparam DWIDTH = HALF_DEPTH ? 11 : 23; 32 | localparam DWIDTH1 = DWIDTH+1; 33 | 34 | wire [5:0] hqTable[256] = '{ 35 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, 36 | 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, 37 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, 38 | 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, 39 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, 40 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, 41 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, 42 | 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, 43 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, 44 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, 45 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, 46 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, 47 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, 48 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, 49 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, 50 | 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 51 | }; 52 | 53 | reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2; 54 | reg [23:0] A, B, D, F, G, H; 55 | reg [7:0] pattern, nextpatt; 56 | reg [1:0] cyc; 57 | 58 | reg curbuf; 59 | reg prevbuf = 0; 60 | wire iobuf = !curbuf; 61 | 62 | wire diff0, diff1; 63 | DiffCheck diffcheck0(Curr1, (cyc == 0) ? Prev0 : (cyc == 1) ? Curr0 : (cyc == 2) ? Prev2 : Next1, diff0); 64 | DiffCheck diffcheck1(Curr1, (cyc == 0) ? Prev1 : (cyc == 1) ? Next0 : (cyc == 2) ? Curr2 : Next2, diff1); 65 | 66 | wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; 67 | 68 | wire [23:0] X = (cyc == 0) ? A : (cyc == 1) ? Prev1 : (cyc == 2) ? Next1 : G; 69 | wire [23:0] blend_result_pre; 70 | Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result_pre); 71 | 72 | wire [DWIDTH:0] Curr20tmp; 73 | wire [23:0] Curr20 = HALF_DEPTH ? h2rgb(Curr20tmp) : Curr20tmp; 74 | wire [DWIDTH:0] Curr21tmp; 75 | wire [23:0] Curr21 = HALF_DEPTH ? h2rgb(Curr21tmp) : Curr21tmp; 76 | 77 | reg [AWIDTH:0] wrin_addr2; 78 | reg [DWIDTH:0] wrpix; 79 | reg wrin_en; 80 | 81 | function [23:0] h2rgb; 82 | input [11:0] v; 83 | begin 84 | h2rgb = mono ? {v[7:0], v[7:0], v[7:0]} : {v[11:8],v[11:8],v[7:4],v[7:4],v[3:0],v[3:0]}; 85 | end 86 | endfunction 87 | 88 | function [11:0] rgb2h; 89 | input [23:0] v; 90 | begin 91 | rgb2h = mono ? {4'b0000, v[23:20], v[19:16]} : {v[23:20], v[15:12], v[7:4]}; 92 | end 93 | endfunction 94 | 95 | hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in 96 | ( 97 | .clk(clk), 98 | 99 | .rdaddr(offs), 100 | .rdbuf0(prevbuf), 101 | .rdbuf1(curbuf), 102 | .q0(Curr20tmp), 103 | .q1(Curr21tmp), 104 | 105 | .wraddr(wrin_addr2), 106 | .wrbuf(iobuf), 107 | .data(wrpix), 108 | .wren(wrin_en) 109 | ); 110 | 111 | reg [AWIDTH+1:0] read_x; 112 | reg [AWIDTH+1:0] wrout_addr; 113 | reg wrout_en; 114 | reg [DWIDTH1*4-1:0] wrdata, wrdata_pre; 115 | wire [DWIDTH1*4-1:0] outpixel_x4; 116 | reg [DWIDTH1*2-1:0] outpixel_x2; 117 | 118 | assign outpixel = read_x[0] ? outpixel_x2[DWIDTH1*2-1:DWIDTH1] : outpixel_x2[DWIDTH:0]; 119 | 120 | hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH+1), .DWIDTH(DWIDTH1*4-1)) hq2x_out 121 | ( 122 | .clock(clk), 123 | 124 | .rdaddress({read_x[AWIDTH+1:1],read_y[1]}), 125 | .q(outpixel_x4), 126 | 127 | .data(wrdata), 128 | .wraddress(wrout_addr), 129 | .wren(wrout_en) 130 | ); 131 | 132 | wire [DWIDTH:0] blend_result = HALF_DEPTH ? rgb2h(blend_result_pre) : blend_result_pre[DWIDTH:0]; 133 | 134 | reg [AWIDTH:0] offs; 135 | always @(posedge clk) begin 136 | reg old_reset_line; 137 | reg old_reset_frame; 138 | 139 | wrout_en <= 0; 140 | wrin_en <= 0; 141 | 142 | if(ce_x4) begin 143 | 144 | pattern <= new_pattern; 145 | if(read_x[0]) outpixel_x2 <= read_y[0] ? outpixel_x4[DWIDTH1*4-1:DWIDTH1*2] : outpixel_x4[DWIDTH1*2-1:0]; 146 | 147 | if(~&offs) begin 148 | if (cyc == 1) begin 149 | Prev2 <= Curr20; 150 | Curr2 <= Curr21; 151 | Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; 152 | wrpix <= inputpixel; 153 | wrin_addr2 <= offs; 154 | wrin_en <= 1; 155 | end 156 | 157 | case({cyc[1],^cyc}) 158 | 0: wrdata[DWIDTH:0] <= blend_result; 159 | 1: wrdata[DWIDTH1+DWIDTH:DWIDTH1] <= blend_result; 160 | 2: wrdata[DWIDTH1*2+DWIDTH:DWIDTH1*2] <= blend_result; 161 | 3: wrdata[DWIDTH1*3+DWIDTH:DWIDTH1*3] <= blend_result; 162 | endcase 163 | 164 | if(cyc==3) begin 165 | offs <= offs + 1'd1; 166 | wrout_addr <= {offs, curbuf}; 167 | wrout_en <= 1; 168 | end 169 | end 170 | 171 | if(cyc==3) begin 172 | nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; 173 | {A, G} <= {Prev0, Next0}; 174 | {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; 175 | {Prev0, Prev1} <= {Prev1, Prev2}; 176 | {Curr0, Curr1} <= {Curr1, Curr2}; 177 | {Next0, Next1} <= {Next1, Next2}; 178 | end else begin 179 | nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; 180 | {B, F, H, D} <= {F, H, D, B}; 181 | end 182 | 183 | cyc <= cyc + 1'b1; 184 | if(old_reset_line && ~reset_line) begin 185 | old_reset_frame <= reset_frame; 186 | offs <= 0; 187 | cyc <= 0; 188 | curbuf <= ~curbuf; 189 | prevbuf <= curbuf; 190 | {Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2} <= '0; 191 | if(old_reset_frame & ~reset_frame) begin 192 | curbuf <= 0; 193 | prevbuf <= 0; 194 | end 195 | end 196 | 197 | if(~hblank & ~&read_x) read_x <= read_x + 1'd1; 198 | if(hblank) read_x <= 0; 199 | 200 | old_reset_line <= reset_line; 201 | end 202 | end 203 | 204 | endmodule 205 | 206 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 207 | 208 | module hq2x_in #(parameter LENGTH, parameter DWIDTH) 209 | ( 210 | input clk, 211 | 212 | input [AWIDTH:0] rdaddr, 213 | input rdbuf0, rdbuf1, 214 | output[DWIDTH:0] q0,q1, 215 | 216 | input [AWIDTH:0] wraddr, 217 | input wrbuf, 218 | input [DWIDTH:0] data, 219 | input wren 220 | ); 221 | 222 | localparam AWIDTH = $clog2(LENGTH)-1; 223 | wire [DWIDTH:0] out[2]; 224 | assign q0 = out[rdbuf0]; 225 | assign q1 = out[rdbuf1]; 226 | 227 | hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); 228 | hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); 229 | endmodule 230 | 231 | module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) 232 | ( 233 | input clock, 234 | input [DWIDTH:0] data, 235 | input [AWIDTH:0] rdaddress, 236 | input [AWIDTH:0] wraddress, 237 | input wren, 238 | output logic [DWIDTH:0] q 239 | ); 240 | 241 | logic [DWIDTH:0] ram[0:NUMWORDS-1]; 242 | 243 | always_ff@(posedge clock) begin 244 | if(wren) ram[wraddress] <= data; 245 | q <= ram[rdaddress]; 246 | end 247 | 248 | endmodule 249 | 250 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 251 | 252 | module DiffCheck 253 | ( 254 | input [23:0] rgb1, 255 | input [23:0] rgb2, 256 | output result 257 | ); 258 | 259 | wire [7:0] r = rgb1[7:1] - rgb2[7:1]; 260 | wire [7:0] g = rgb1[15:9] - rgb2[15:9]; 261 | wire [7:0] b = rgb1[23:17] - rgb2[23:17]; 262 | wire [8:0] t = $signed(r) + $signed(b); 263 | wire [8:0] gx = {g[7], g}; 264 | wire [9:0] y = $signed(t) + $signed(gx); 265 | wire [8:0] u = $signed(r) - $signed(b); 266 | wire [9:0] v = $signed({g, 1'b0}) - $signed(t); 267 | 268 | // if y is inside (-96..96) 269 | wire y_inside = (y < 10'h60 || y >= 10'h3a0); 270 | 271 | // if u is inside (-16, 16) 272 | wire u_inside = (u < 9'h10 || u >= 9'h1f0); 273 | 274 | // if v is inside (-24, 24) 275 | wire v_inside = (v < 10'h18 || v >= 10'h3e8); 276 | assign result = !(y_inside && u_inside && v_inside); 277 | endmodule 278 | 279 | module InnerBlend 280 | ( 281 | input [8:0] Op, 282 | input [7:0] A, 283 | input [7:0] B, 284 | input [7:0] C, 285 | output [7:0] O 286 | ); 287 | 288 | function [10:0] mul8x3; 289 | input [7:0] op1; 290 | input [2:0] op2; 291 | begin 292 | mul8x3 = 11'd0; 293 | if(op2[0]) mul8x3 = mul8x3 + op1; 294 | if(op2[1]) mul8x3 = mul8x3 + {op1, 1'b0}; 295 | if(op2[2]) mul8x3 = mul8x3 + {op1, 2'b00}; 296 | end 297 | endfunction 298 | 299 | wire OpOnes = Op[4]; 300 | wire [10:0] Amul = mul8x3(A, Op[7:5]); 301 | wire [10:0] Bmul = mul8x3(B, {Op[3:2], 1'b0}); 302 | wire [10:0] Cmul = mul8x3(C, {Op[1:0], 1'b0}); 303 | wire [10:0] At = Amul; 304 | wire [10:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; 305 | wire [10:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; 306 | wire [11:0] Res = {At, 1'b0} + Bt + Ct; 307 | assign O = Op[8] ? A : Res[11:4]; 308 | endmodule 309 | 310 | module Blend 311 | ( 312 | input [5:0] rule, 313 | input disable_hq2x, 314 | input [23:0] E, 315 | input [23:0] A, 316 | input [23:0] B, 317 | input [23:0] D, 318 | input [23:0] F, 319 | input [23:0] H, 320 | output [23:0] Result 321 | ); 322 | 323 | reg [1:0] input_ctrl; 324 | reg [8:0] op; 325 | localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A 326 | localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 327 | localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 328 | localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 329 | localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 330 | localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 331 | localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 332 | localparam AB = 2'b00; 333 | localparam AD = 2'b01; 334 | localparam DB = 2'b10; 335 | localparam BD = 2'b11; 336 | wire is_diff; 337 | DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); 338 | 339 | always @* begin 340 | case({!is_diff, rule[5:2]}) 341 | 1,17: {op, input_ctrl} = {BLEND1, AB}; 342 | 2,18: {op, input_ctrl} = {BLEND1, DB}; 343 | 3,19: {op, input_ctrl} = {BLEND1, BD}; 344 | 4,20: {op, input_ctrl} = {BLEND2, DB}; 345 | 5,21: {op, input_ctrl} = {BLEND2, AB}; 346 | 6,22: {op, input_ctrl} = {BLEND2, AD}; 347 | 348 | 8: {op, input_ctrl} = {BLEND0, 2'bxx}; 349 | 9: {op, input_ctrl} = {BLEND0, 2'bxx}; 350 | 10: {op, input_ctrl} = {BLEND0, 2'bxx}; 351 | 11: {op, input_ctrl} = {BLEND1, AB}; 352 | 12: {op, input_ctrl} = {BLEND1, AB}; 353 | 13: {op, input_ctrl} = {BLEND1, AB}; 354 | 14: {op, input_ctrl} = {BLEND1, DB}; 355 | 15: {op, input_ctrl} = {BLEND1, BD}; 356 | 357 | 24: {op, input_ctrl} = {BLEND2, DB}; 358 | 25: {op, input_ctrl} = {BLEND5, DB}; 359 | 26: {op, input_ctrl} = {BLEND6, DB}; 360 | 27: {op, input_ctrl} = {BLEND2, DB}; 361 | 28: {op, input_ctrl} = {BLEND4, DB}; 362 | 29: {op, input_ctrl} = {BLEND5, DB}; 363 | 30: {op, input_ctrl} = {BLEND3, BD}; 364 | 31: {op, input_ctrl} = {BLEND3, DB}; 365 | default: {op, input_ctrl} = {11{1'bx}}; 366 | endcase 367 | 368 | // Setting op[8] effectively disables HQ2X because blend will always return E. 369 | if (disable_hq2x) op[8] = 1; 370 | end 371 | 372 | // Generate inputs to the inner blender. Valid combinations. 373 | // 00: E A B 374 | // 01: E A D 375 | // 10: E D B 376 | // 11: E B D 377 | wire [23:0] Input1 = E; 378 | wire [23:0] Input2 = !input_ctrl[1] ? A : 379 | !input_ctrl[0] ? D : B; 380 | 381 | wire [23:0] Input3 = !input_ctrl[0] ? B : D; 382 | InnerBlend inner_blend1(op, Input1[7:0], Input2[7:0], Input3[7:0], Result[7:0]); 383 | InnerBlend inner_blend2(op, Input1[15:8], Input2[15:8], Input3[15:8], Result[15:8]); 384 | InnerBlend inner_blend3(op, Input1[23:16], Input2[23:16], Input3[23:16], Result[23:16]); 385 | endmodule 386 | -------------------------------------------------------------------------------- /sys/spdif.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // SPDIF Transmitter 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2012 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | // altera message_off 10762 31 | // altera message_off 10240 32 | 33 | module spdif 34 | 35 | //----------------------------------------------------------------- 36 | // Params 37 | //----------------------------------------------------------------- 38 | #( 39 | parameter CLK_RATE = 50000000, 40 | parameter AUDIO_RATE = 48000, 41 | 42 | // Generated params 43 | parameter WHOLE_CYCLES = (CLK_RATE) / (AUDIO_RATE*128), 44 | parameter ERROR_BASE = 10000, 45 | parameter [63:0] ERRORS_PER_BIT = ((CLK_RATE * ERROR_BASE) / (AUDIO_RATE*128)) - (WHOLE_CYCLES * ERROR_BASE) 46 | ) 47 | 48 | //----------------------------------------------------------------- 49 | // Ports 50 | //----------------------------------------------------------------- 51 | ( 52 | input clk_i, 53 | input rst_i, 54 | input half_rate, 55 | 56 | // Output 57 | output spdif_o, 58 | 59 | // Audio interface (16-bit x 2 = RL) 60 | input [15:0] audio_r, 61 | input [15:0] audio_l, 62 | output sample_req_o 63 | ); 64 | 65 | reg lpf_ce; 66 | always @(posedge clk_i) begin 67 | reg [2:0] div; 68 | 69 | if(bit_clk_q) div <= div + 1'd1; 70 | lpf_ce <= !div; 71 | end 72 | 73 | wire [15:0] al, ar; 74 | 75 | lpf_spdif lpf_l 76 | ( 77 | .CLK(clk_i), 78 | .CE(lpf_ce), 79 | .IDATA(audio_l), 80 | .ODATA(al) 81 | ); 82 | 83 | lpf_spdif lpf_r 84 | ( 85 | .CLK(clk_i), 86 | .CE(lpf_ce), 87 | 88 | .IDATA(audio_r), 89 | .ODATA(ar) 90 | ); 91 | 92 | reg bit_clk_q; 93 | 94 | // Clock pulse generator 95 | always @ (posedge rst_i or posedge clk_i) begin 96 | reg [31:0] count_q; 97 | reg [31:0] error_q; 98 | reg ce; 99 | 100 | if (rst_i) begin 101 | count_q <= 0; 102 | error_q <= 0; 103 | bit_clk_q <= 1; 104 | ce <= 0; 105 | end 106 | else 107 | begin 108 | if(count_q == WHOLE_CYCLES-1) begin 109 | if (error_q < (ERROR_BASE - ERRORS_PER_BIT)) begin 110 | error_q <= error_q + ERRORS_PER_BIT[31:0]; 111 | count_q <= 0; 112 | end else begin 113 | error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE; 114 | count_q <= count_q + 1; 115 | end 116 | end else if(count_q == WHOLE_CYCLES) begin 117 | count_q <= 0; 118 | end else begin 119 | count_q <= count_q + 1; 120 | end 121 | 122 | bit_clk_q <= 0; 123 | if(!count_q) begin 124 | ce <= ~ce; 125 | if(~half_rate || ce) bit_clk_q <= 1; 126 | end 127 | end 128 | end 129 | 130 | //----------------------------------------------------------------- 131 | // Core SPDIF 132 | //----------------------------------------------------------------- 133 | 134 | wire [31:0] sample_i = {ar, al}; 135 | 136 | spdif_core 137 | u_core 138 | ( 139 | .clk_i(clk_i), 140 | .rst_i(rst_i), 141 | 142 | .bit_out_en_i(bit_clk_q), 143 | 144 | .spdif_o(spdif_o), 145 | 146 | .sample_i(sample_i), 147 | .sample_req_o(sample_req_o) 148 | ); 149 | 150 | endmodule 151 | 152 | module spdif_core 153 | ( 154 | input clk_i, 155 | input rst_i, 156 | 157 | // SPDIF bit output enable 158 | // Single cycle pulse synchronous to clk_i which drives 159 | // the output bit rate. 160 | // For 44.1KHz, 44100×32×2×2 = 5,644,800Hz 161 | // For 48KHz, 48000×32×2×2 = 6,144,000Hz 162 | input bit_out_en_i, 163 | 164 | // Output 165 | output spdif_o, 166 | 167 | // Audio interface (16-bit x 2 = RL) 168 | input [31:0] sample_i, 169 | output reg sample_req_o 170 | ); 171 | 172 | //----------------------------------------------------------------- 173 | // Registers 174 | //----------------------------------------------------------------- 175 | reg [15:0] audio_sample_q; 176 | reg [8:0] subframe_count_q; 177 | 178 | reg load_subframe_q; 179 | reg [7:0] preamble_q; 180 | wire [31:0] subframe_w; 181 | 182 | reg [5:0] bit_count_q; 183 | reg bit_toggle_q; 184 | 185 | reg spdif_out_q; 186 | 187 | reg [5:0] parity_count_q; 188 | 189 | //----------------------------------------------------------------- 190 | // Subframe Counter 191 | //----------------------------------------------------------------- 192 | always @ (posedge rst_i or posedge clk_i ) 193 | begin 194 | if (rst_i == 1'b1) 195 | subframe_count_q <= 9'd0; 196 | else if (load_subframe_q) 197 | begin 198 | // 192 frames (384 subframes) in an audio block 199 | if (subframe_count_q == 9'd383) 200 | subframe_count_q <= 9'd0; 201 | else 202 | subframe_count_q <= subframe_count_q + 9'd1; 203 | end 204 | end 205 | 206 | //----------------------------------------------------------------- 207 | // Sample capture 208 | //----------------------------------------------------------------- 209 | reg [15:0] sample_buf_q; 210 | 211 | always @ (posedge rst_i or posedge clk_i ) 212 | begin 213 | if (rst_i == 1'b1) 214 | begin 215 | audio_sample_q <= 16'h0000; 216 | sample_buf_q <= 16'h0000; 217 | sample_req_o <= 1'b0; 218 | end 219 | else if (load_subframe_q) 220 | begin 221 | // Start of frame (first subframe)? 222 | if (subframe_count_q[0] == 1'b0) 223 | begin 224 | // Use left sample 225 | audio_sample_q <= sample_i[15:0]; 226 | 227 | // Store right sample 228 | sample_buf_q <= sample_i[31:16]; 229 | 230 | // Request next sample 231 | sample_req_o <= 1'b1; 232 | end 233 | else 234 | begin 235 | // Use right sample 236 | audio_sample_q <= sample_buf_q; 237 | 238 | sample_req_o <= 1'b0; 239 | end 240 | end 241 | else 242 | sample_req_o <= 1'b0; 243 | end 244 | 245 | // Timeslots 3 - 0 = Preamble 246 | assign subframe_w[3:0] = 4'b0000; 247 | 248 | // Timeslots 7 - 4 = 24-bit audio LSB 249 | assign subframe_w[7:4] = 4'b0000; 250 | 251 | // Timeslots 11 - 8 = 20-bit audio LSB 252 | assign subframe_w[11:8] = 4'b0000; 253 | 254 | // Timeslots 27 - 12 = 16-bit audio 255 | assign subframe_w[27:12] = audio_sample_q; 256 | 257 | // Timeslots 28 = Validity 258 | assign subframe_w[28] = 1'b0; // Valid 259 | 260 | // Timeslots 29 = User bit 261 | assign subframe_w[29] = 1'b0; 262 | 263 | // Timeslots 30 = Channel status bit 264 | assign subframe_w[30] = 1'b0; 265 | 266 | // Timeslots 31 = Even Parity bit (31:4) 267 | assign subframe_w[31] = 1'b0; 268 | 269 | //----------------------------------------------------------------- 270 | // Preamble 271 | //----------------------------------------------------------------- 272 | localparam PREAMBLE_Z = 8'b00010111; 273 | localparam PREAMBLE_Y = 8'b00100111; 274 | localparam PREAMBLE_X = 8'b01000111; 275 | 276 | reg [7:0] preamble_r; 277 | 278 | always @ * 279 | begin 280 | // Start of audio block? 281 | // Z(B) - Left channel 282 | if (subframe_count_q == 9'd0) 283 | preamble_r = PREAMBLE_Z; // Z(B) 284 | // Right Channel? 285 | else if (subframe_count_q[0] == 1'b1) 286 | preamble_r = PREAMBLE_Y; // Y(W) 287 | // Left Channel (but not start of block)? 288 | else 289 | preamble_r = PREAMBLE_X; // X(M) 290 | end 291 | 292 | always @ (posedge rst_i or posedge clk_i ) 293 | if (rst_i == 1'b1) 294 | preamble_q <= 8'h00; 295 | else if (load_subframe_q) 296 | preamble_q <= preamble_r; 297 | 298 | //----------------------------------------------------------------- 299 | // Parity Counter 300 | //----------------------------------------------------------------- 301 | always @ (posedge rst_i or posedge clk_i ) 302 | begin 303 | if (rst_i == 1'b1) 304 | begin 305 | parity_count_q <= 6'd0; 306 | end 307 | // Time to output a bit? 308 | else if (bit_out_en_i) 309 | begin 310 | // Preamble bits? 311 | if (bit_count_q < 6'd8) 312 | begin 313 | parity_count_q <= 6'd0; 314 | end 315 | // Normal timeslots 316 | else if (bit_count_q < 6'd62) 317 | begin 318 | // On first pass through this timeslot, count number of high bits 319 | if (bit_count_q[0] == 0 && subframe_w[bit_count_q / 2] == 1'b1) 320 | parity_count_q <= parity_count_q + 6'd1; 321 | end 322 | end 323 | end 324 | 325 | //----------------------------------------------------------------- 326 | // Bit Counter 327 | //----------------------------------------------------------------- 328 | always @ (posedge rst_i or posedge clk_i) 329 | begin 330 | if (rst_i == 1'b1) 331 | begin 332 | bit_count_q <= 6'b0; 333 | load_subframe_q <= 1'b1; 334 | end 335 | // Time to output a bit? 336 | else if (bit_out_en_i) 337 | begin 338 | // 32 timeslots (x2 for double frequency) 339 | if (bit_count_q == 6'd63) 340 | begin 341 | bit_count_q <= 6'd0; 342 | load_subframe_q <= 1'b1; 343 | end 344 | else 345 | begin 346 | bit_count_q <= bit_count_q + 6'd1; 347 | load_subframe_q <= 1'b0; 348 | end 349 | end 350 | else 351 | load_subframe_q <= 1'b0; 352 | end 353 | 354 | //----------------------------------------------------------------- 355 | // Bit half toggle 356 | //----------------------------------------------------------------- 357 | always @ (posedge rst_i or posedge clk_i) 358 | if (rst_i == 1'b1) 359 | bit_toggle_q <= 1'b0; 360 | // Time to output a bit? 361 | else if (bit_out_en_i) 362 | bit_toggle_q <= ~bit_toggle_q; 363 | 364 | //----------------------------------------------------------------- 365 | // Output bit (BMC encoded) 366 | //----------------------------------------------------------------- 367 | reg bit_r; 368 | 369 | always @ * 370 | begin 371 | bit_r = spdif_out_q; 372 | 373 | // Time to output a bit? 374 | if (bit_out_en_i) 375 | begin 376 | // Preamble bits? 377 | if (bit_count_q < 6'd8) 378 | begin 379 | bit_r = preamble_q[bit_count_q[2:0]]; 380 | end 381 | // Normal timeslots 382 | else if (bit_count_q < 6'd62) 383 | begin 384 | if (subframe_w[bit_count_q / 2] == 1'b0) 385 | begin 386 | if (bit_toggle_q == 1'b0) 387 | bit_r = ~spdif_out_q; 388 | else 389 | bit_r = spdif_out_q; 390 | end 391 | else 392 | bit_r = ~spdif_out_q; 393 | end 394 | // Parity timeslot 395 | else 396 | begin 397 | // Even number of high bits, make odd 398 | if (parity_count_q[0] == 1'b0) 399 | begin 400 | if (bit_toggle_q == 1'b0) 401 | bit_r = ~spdif_out_q; 402 | else 403 | bit_r = spdif_out_q; 404 | end 405 | else 406 | bit_r = ~spdif_out_q; 407 | end 408 | end 409 | end 410 | 411 | always @ (posedge rst_i or posedge clk_i ) 412 | if (rst_i == 1'b1) 413 | spdif_out_q <= 1'b0; 414 | else 415 | spdif_out_q <= bit_r; 416 | 417 | assign spdif_o = spdif_out_q; 418 | 419 | endmodule 420 | 421 | module lpf_spdif 422 | ( 423 | input CLK, 424 | input CE, 425 | input [15:0] IDATA, 426 | output reg [15:0] ODATA 427 | ); 428 | 429 | reg [511:0] acc; 430 | reg [20:0] sum; 431 | 432 | always @(*) begin 433 | integer i; 434 | sum = 0; 435 | for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]}; 436 | end 437 | 438 | always @(posedge CLK) begin 439 | if(CE) begin 440 | acc <= {acc[495:0], IDATA}; 441 | ODATA <= sum[20:5]; 442 | end 443 | end 444 | 445 | endmodule 446 | -------------------------------------------------------------------------------- /src/cpu/tv80_alu.v: -------------------------------------------------------------------------------- 1 | // 2 | // TV80 8-Bit Microprocessor Core 3 | // Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) 4 | // 5 | // Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a 8 | // copy of this software and associated documentation files (the "Software"), 9 | // to deal in the Software without restriction, including without limitation 10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | // and/or sell copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included 15 | // in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | module tv80_alu (/*AUTOARG*/ 26 | // Outputs 27 | Q, F_Out, 28 | // Inputs 29 | Arith16, Z16, ALU_Op, IR, ISet, BusA, BusB, F_In 30 | ); 31 | 32 | parameter Mode = 0; 33 | parameter Flag_C = 0; 34 | parameter Flag_N = 1; 35 | parameter Flag_P = 2; 36 | parameter Flag_X = 3; 37 | parameter Flag_H = 4; 38 | parameter Flag_Y = 5; 39 | parameter Flag_Z = 6; 40 | parameter Flag_S = 7; 41 | 42 | input Arith16; 43 | input Z16; 44 | input [3:0] ALU_Op ; 45 | input [5:0] IR; 46 | input [1:0] ISet; 47 | input [7:0] BusA; 48 | input [7:0] BusB; 49 | input [7:0] F_In; 50 | output [7:0] Q; 51 | output [7:0] F_Out; 52 | reg [7:0] Q; 53 | reg [7:0] F_Out; 54 | 55 | function [4:0] AddSub4; 56 | input [3:0] A; 57 | input [3:0] B; 58 | input Sub; 59 | input Carry_In; 60 | begin 61 | AddSub4 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; 62 | end 63 | endfunction // AddSub4 64 | 65 | function [3:0] AddSub3; 66 | input [2:0] A; 67 | input [2:0] B; 68 | input Sub; 69 | input Carry_In; 70 | begin 71 | AddSub3 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; 72 | end 73 | endfunction // AddSub4 74 | 75 | function [1:0] AddSub1; 76 | input A; 77 | input B; 78 | input Sub; 79 | input Carry_In; 80 | begin 81 | AddSub1 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + Carry_In; 82 | end 83 | endfunction // AddSub4 84 | 85 | // AddSub variables (temporary signals) 86 | reg UseCarry; 87 | reg Carry7_v; 88 | reg OverFlow_v; 89 | reg HalfCarry_v; 90 | reg Carry_v; 91 | reg [7:0] Q_v; 92 | 93 | reg [7:0] BitMask; 94 | 95 | 96 | always @(/*AUTOSENSE*/ALU_Op or BusA or BusB or F_In or IR) 97 | begin 98 | case (IR[5:3]) 99 | 3'b000 : BitMask = 8'b00000001; 100 | 3'b001 : BitMask = 8'b00000010; 101 | 3'b010 : BitMask = 8'b00000100; 102 | 3'b011 : BitMask = 8'b00001000; 103 | 3'b100 : BitMask = 8'b00010000; 104 | 3'b101 : BitMask = 8'b00100000; 105 | 3'b110 : BitMask = 8'b01000000; 106 | default: BitMask = 8'b10000000; 107 | endcase // case(IR[5:3]) 108 | 109 | UseCarry = ~ ALU_Op[2] && ALU_Op[0]; 110 | { HalfCarry_v, Q_v[3:0] } = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1], ALU_Op[1] ^ (UseCarry && F_In[Flag_C]) ); 111 | { Carry7_v, Q_v[6:4] } = AddSub3(BusA[6:4], BusB[6:4], ALU_Op[1], HalfCarry_v); 112 | { Carry_v, Q_v[7] } = AddSub1(BusA[7], BusB[7], ALU_Op[1], Carry7_v); 113 | OverFlow_v = Carry_v ^ Carry7_v; 114 | end // always @ * 115 | 116 | reg [7:0] Q_t; 117 | reg [8:0] DAA_Q; 118 | 119 | always @ (/*AUTOSENSE*/ALU_Op or Arith16 or BitMask or BusA or BusB 120 | or Carry_v or F_In or HalfCarry_v or IR or ISet 121 | or OverFlow_v or Q_v or Z16) 122 | begin 123 | Q_t = 8'hxx; 124 | DAA_Q = {9{1'bx}}; 125 | 126 | F_Out = F_In; 127 | case (ALU_Op) 128 | 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 : 129 | begin 130 | F_Out[Flag_N] = 1'b0; 131 | F_Out[Flag_C] = 1'b0; 132 | 133 | case (ALU_Op[2:0]) 134 | 135 | 3'b000, 3'b001 : // ADD, ADC 136 | begin 137 | Q_t = Q_v; 138 | F_Out[Flag_C] = Carry_v; 139 | F_Out[Flag_H] = HalfCarry_v; 140 | F_Out[Flag_P] = OverFlow_v; 141 | end 142 | 143 | 3'b010, 3'b011, 3'b111 : // SUB, SBC, CP 144 | begin 145 | Q_t = Q_v; 146 | F_Out[Flag_N] = 1'b1; 147 | F_Out[Flag_C] = ~ Carry_v; 148 | F_Out[Flag_H] = ~ HalfCarry_v; 149 | F_Out[Flag_P] = OverFlow_v; 150 | end 151 | 152 | 3'b100 : // AND 153 | begin 154 | Q_t[7:0] = BusA & BusB; 155 | F_Out[Flag_H] = 1'b1; 156 | end 157 | 158 | 3'b101 : // XOR 159 | begin 160 | Q_t[7:0] = BusA ^ BusB; 161 | F_Out[Flag_H] = 1'b0; 162 | end 163 | 164 | default : // OR 3'b110 165 | begin 166 | Q_t[7:0] = BusA | BusB; 167 | F_Out[Flag_H] = 1'b0; 168 | end 169 | 170 | endcase // case(ALU_OP[2:0]) 171 | 172 | if (ALU_Op[2:0] == 3'b111 ) 173 | begin // CP 174 | F_Out[Flag_X] = BusB[3]; 175 | F_Out[Flag_Y] = BusB[5]; 176 | end 177 | else 178 | begin 179 | F_Out[Flag_X] = Q_t[3]; 180 | F_Out[Flag_Y] = Q_t[5]; 181 | end 182 | 183 | if (Q_t[7:0] == 8'b00000000 ) 184 | begin 185 | F_Out[Flag_Z] = 1'b1; 186 | if (Z16 == 1'b1 ) 187 | begin 188 | F_Out[Flag_Z] = F_In[Flag_Z]; // 16 bit ADC,SBC 189 | end 190 | end 191 | else 192 | begin 193 | F_Out[Flag_Z] = 1'b0; 194 | end // else: !if(Q_t[7:0] == 8'b00000000 ) 195 | 196 | F_Out[Flag_S] = Q_t[7]; 197 | case (ALU_Op[2:0]) 198 | 3'b000, 3'b001, 3'b010, 3'b011, 3'b111 : // ADD, ADC, SUB, SBC, CP 199 | ; 200 | 201 | default : 202 | F_Out[Flag_P] = ~(^Q_t); 203 | endcase // case(ALU_Op[2:0]) 204 | 205 | if (Arith16 == 1'b1 ) 206 | begin 207 | F_Out[Flag_S] = F_In[Flag_S]; 208 | F_Out[Flag_Z] = F_In[Flag_Z]; 209 | F_Out[Flag_P] = F_In[Flag_P]; 210 | end 211 | end // case: 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 212 | 213 | 4'b1100 : 214 | begin 215 | // DAA 216 | F_Out[Flag_H] = F_In[Flag_H]; 217 | F_Out[Flag_C] = F_In[Flag_C]; 218 | DAA_Q[7:0] = BusA; 219 | DAA_Q[8] = 1'b0; 220 | if (F_In[Flag_N] == 1'b0 ) 221 | begin 222 | // After addition 223 | // Alow > 9 || H == 1 224 | if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) 225 | begin 226 | if ((DAA_Q[3:0] > 9) ) 227 | begin 228 | F_Out[Flag_H] = 1'b1; 229 | end 230 | else 231 | begin 232 | F_Out[Flag_H] = 1'b0; 233 | end 234 | DAA_Q = DAA_Q + 6; 235 | end // if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) 236 | 237 | // new Ahigh > 9 || C == 1 238 | if (DAA_Q[8:4] > 9 || F_In[Flag_C] == 1'b1 ) 239 | begin 240 | DAA_Q = DAA_Q + 96; // 0x60 241 | end 242 | end 243 | else 244 | begin 245 | // After subtraction 246 | if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 ) 247 | begin 248 | if (DAA_Q[3:0] > 5 ) 249 | begin 250 | F_Out[Flag_H] = 1'b0; 251 | end 252 | DAA_Q[7:0] = DAA_Q[7:0] - 6; 253 | end 254 | if (BusA > 153 || F_In[Flag_C] == 1'b1 ) 255 | begin 256 | DAA_Q = DAA_Q - 352; // 0x160 257 | end 258 | end // else: !if(F_In[Flag_N] == 1'b0 ) 259 | 260 | F_Out[Flag_X] = DAA_Q[3]; 261 | F_Out[Flag_Y] = DAA_Q[5]; 262 | F_Out[Flag_C] = F_In[Flag_C] || DAA_Q[8]; 263 | Q_t = DAA_Q[7:0]; 264 | 265 | if (DAA_Q[7:0] == 8'b00000000 ) 266 | begin 267 | F_Out[Flag_Z] = 1'b1; 268 | end 269 | else 270 | begin 271 | F_Out[Flag_Z] = 1'b0; 272 | end 273 | 274 | F_Out[Flag_S] = DAA_Q[7]; 275 | F_Out[Flag_P] = ~ (^DAA_Q); 276 | end // case: 4'b1100 277 | 278 | 4'b1101, 4'b1110 : 279 | begin 280 | // RLD, RRD 281 | Q_t[7:4] = BusA[7:4]; 282 | if (ALU_Op[0] == 1'b1 ) 283 | begin 284 | Q_t[3:0] = BusB[7:4]; 285 | end 286 | else 287 | begin 288 | Q_t[3:0] = BusB[3:0]; 289 | end 290 | F_Out[Flag_H] = 1'b0; 291 | F_Out[Flag_N] = 1'b0; 292 | F_Out[Flag_X] = Q_t[3]; 293 | F_Out[Flag_Y] = Q_t[5]; 294 | if (Q_t[7:0] == 8'b00000000 ) 295 | begin 296 | F_Out[Flag_Z] = 1'b1; 297 | end 298 | else 299 | begin 300 | F_Out[Flag_Z] = 1'b0; 301 | end 302 | F_Out[Flag_S] = Q_t[7]; 303 | F_Out[Flag_P] = ~(^Q_t); 304 | end // case: when 4'b1101, 4'b1110 305 | 306 | 4'b1001 : 307 | begin 308 | // BIT 309 | Q_t[7:0] = BusB & BitMask; 310 | F_Out[Flag_S] = Q_t[7]; 311 | if (Q_t[7:0] == 8'b00000000 ) 312 | begin 313 | F_Out[Flag_Z] = 1'b1; 314 | F_Out[Flag_P] = 1'b1; 315 | end 316 | else 317 | begin 318 | F_Out[Flag_Z] = 1'b0; 319 | F_Out[Flag_P] = 1'b0; 320 | end 321 | F_Out[Flag_H] = 1'b1; 322 | F_Out[Flag_N] = 1'b0; 323 | F_Out[Flag_X] = 1'b0; 324 | F_Out[Flag_Y] = 1'b0; 325 | if (IR[2:0] != 3'b110 ) 326 | begin 327 | F_Out[Flag_X] = BusB[3]; 328 | F_Out[Flag_Y] = BusB[5]; 329 | end 330 | end // case: when 4'b1001 331 | 332 | 4'b1010 : 333 | // SET 334 | Q_t[7:0] = BusB | BitMask; 335 | 336 | 4'b1011 : 337 | // RES 338 | Q_t[7:0] = BusB & ~ BitMask; 339 | 340 | 4'b1000 : 341 | begin 342 | // ROT 343 | case (IR[5:3]) 344 | 3'b000 : // RLC 345 | begin 346 | Q_t[7:1] = BusA[6:0]; 347 | Q_t[0] = BusA[7]; 348 | F_Out[Flag_C] = BusA[7]; 349 | end 350 | 351 | 3'b010 : // RL 352 | begin 353 | Q_t[7:1] = BusA[6:0]; 354 | Q_t[0] = F_In[Flag_C]; 355 | F_Out[Flag_C] = BusA[7]; 356 | end 357 | 358 | 3'b001 : // RRC 359 | begin 360 | Q_t[6:0] = BusA[7:1]; 361 | Q_t[7] = BusA[0]; 362 | F_Out[Flag_C] = BusA[0]; 363 | end 364 | 365 | 3'b011 : // RR 366 | begin 367 | Q_t[6:0] = BusA[7:1]; 368 | Q_t[7] = F_In[Flag_C]; 369 | F_Out[Flag_C] = BusA[0]; 370 | end 371 | 372 | 3'b100 : // SLA 373 | begin 374 | Q_t[7:1] = BusA[6:0]; 375 | Q_t[0] = 1'b0; 376 | F_Out[Flag_C] = BusA[7]; 377 | end 378 | 379 | 3'b110 : // SLL (Undocumented) / SWAP 380 | begin 381 | if (Mode == 3 ) 382 | begin 383 | Q_t[7:4] = BusA[3:0]; 384 | Q_t[3:0] = BusA[7:4]; 385 | F_Out[Flag_C] = 1'b0; 386 | end 387 | else 388 | begin 389 | Q_t[7:1] = BusA[6:0]; 390 | Q_t[0] = 1'b1; 391 | F_Out[Flag_C] = BusA[7]; 392 | end // else: !if(Mode == 3 ) 393 | end // case: 3'b110 394 | 395 | 3'b101 : // SRA 396 | begin 397 | Q_t[6:0] = BusA[7:1]; 398 | Q_t[7] = BusA[7]; 399 | F_Out[Flag_C] = BusA[0]; 400 | end 401 | 402 | default : // SRL 403 | begin 404 | Q_t[6:0] = BusA[7:1]; 405 | Q_t[7] = 1'b0; 406 | F_Out[Flag_C] = BusA[0]; 407 | end 408 | endcase // case(IR[5:3]) 409 | 410 | F_Out[Flag_H] = 1'b0; 411 | F_Out[Flag_N] = 1'b0; 412 | F_Out[Flag_X] = Q_t[3]; 413 | F_Out[Flag_Y] = Q_t[5]; 414 | F_Out[Flag_S] = Q_t[7]; 415 | if (Q_t[7:0] == 8'b00000000 ) 416 | begin 417 | F_Out[Flag_Z] = 1'b1; 418 | end 419 | else 420 | begin 421 | F_Out[Flag_Z] = 1'b0; 422 | end 423 | F_Out[Flag_P] = ~(^Q_t); 424 | 425 | if (ISet == 2'b00 ) 426 | begin 427 | F_Out[Flag_P] = F_In[Flag_P]; 428 | F_Out[Flag_S] = F_In[Flag_S]; 429 | F_Out[Flag_Z] = F_In[Flag_Z]; 430 | end 431 | end // case: 4'b1000 432 | 433 | 434 | default : 435 | ; 436 | 437 | endcase // case(ALU_Op) 438 | 439 | Q = Q_t; 440 | end // always @ (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) 441 | 442 | endmodule // T80_ALU 443 | --------------------------------------------------------------------------------