From f60dec4ef86f4675b67758ed27de223d65cdef41 Mon Sep 17 00:00:00 2001 From: Alan Steremberg Date: Sat, 25 May 2024 14:10:50 -0400 Subject: [PATCH] new sys, release --- Arcade-Druaga.qsf | 82 +- Arcade-Druaga.sv | 1 + sys/arcade_video.v | 5 + sys/hps_io.sv | 34 +- sys/mcp23009.sv | 17 +- sys/pll_cfg.qip | 43 +- sys/pll_cfg/altera_pll_reconfig_core.v | 6 +- sys/pll_cfg/altera_pll_reconfig_top.v | 2 +- sys/{ => pll_cfg}/pll_cfg.v | 0 sys/pll_cfg/pll_cfg_hdmi.v | 1282 ++++++++++++++++++++++++ sys/pll_q13.qip | 4 +- sys/sys.tcl | 7 - sys/sys_top.sdc | 6 +- sys/sys_top.v | 878 ++++++++-------- sys/vga_out.sv | 47 +- sys/video_freak.sv | 77 +- sys/yc_out.sv | 15 +- 17 files changed, 1962 insertions(+), 544 deletions(-) rename sys/{ => pll_cfg}/pll_cfg.v (100%) create mode 100644 sys/pll_cfg/pll_cfg_hdmi.v diff --git a/Arcade-Druaga.qsf b/Arcade-Druaga.qsf index d379970..ea2913e 100644 --- a/Arcade-Druaga.qsf +++ b/Arcade-Druaga.qsf @@ -9,48 +9,48 @@ # -------------------------------------------------------------------------- set_global_assignment -name TOP_LEVEL_ENTITY sys_top -set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top -set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top -set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top -set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Lite Edition" +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Lite Edition" -set_global_assignment -name GENERATE_RBF_FILE ON -set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files -set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL -set_global_assignment -name SAVE_DISK_SPACE OFF -set_global_assignment -name SMART_RECOMPILE ON -set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" -set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 -set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" -set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" -set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF -set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF -set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS -set_global_assignment -name FITTER_EFFORT "STANDARD FIT" -set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" -set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON -set_global_assignment -name QII_AUTO_PACKED_REGISTERS NORMAL -set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON -set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON -set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON -set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON -set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED -set_global_assignment -name MUX_RESTRUCTURE ON -set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON -set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON -set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON -set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON -set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON -set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON -set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON -set_global_assignment -name ECO_OPTIMIZE_TIMING ON -set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON -set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON -set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW -set_global_assignment -name SEED 1 +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name QII_AUTO_PACKED_REGISTERS NORMAL +set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name MUX_RESTRUCTURE ON +set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON +set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON +set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON +set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON +set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON +set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON +set_global_assignment -name ECO_OPTIMIZE_TIMING ON +set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON +set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW +set_global_assignment -name SEED 1 -set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" +set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" #enable it only if 8bit indexed mode is used in core #set_global_assignment -name VERILOG_MACRO "MISTER_FB_PALETTE=1" @@ -70,6 +70,6 @@ set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" source sys/sys.tcl source sys/sys_analog.tcl source files.qip -set_global_assignment -name FLOW_ENABLE_RTL_VIEWER OFF -set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name FLOW_ENABLE_RTL_VIEWER OFF +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade-Druaga.sv b/Arcade-Druaga.sv index fa6dc27..d380dc8 100644 --- a/Arcade-Druaga.sv +++ b/Arcade-Druaga.sv @@ -170,6 +170,7 @@ assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQM assign VGA_F1 = 0; assign VGA_SCALER = 0; assign VGA_DISABLE = 0; +assign FB_FORCE_BLANK = 0; assign HDMI_FREEZE = 0; assign AUDIO_MIX = 0; diff --git a/sys/arcade_video.v b/sys/arcade_video.v index f53b136..f41d042 100644 --- a/sys/arcade_video.v +++ b/sys/arcade_video.v @@ -99,6 +99,11 @@ generate assign G = {RGB_fix[7:4],RGB_fix[7:4]}; assign B = {RGB_fix[3:0],RGB_fix[3:0]}; end + else if(DW == 18) begin + assign R = {RGB_fix[17:12],RGB_fix[17:16]}; + assign G = {RGB_fix[11: 6],RGB_fix[11:10]}; + assign B = {RGB_fix[ 5: 0],RGB_fix[ 5: 4]}; + end else begin // 24 assign R = RGB_fix[23:16]; assign G = RGB_fix[15:8]; diff --git a/sys/hps_io.sv b/sys/hps_io.sv index bf61f35..4fac671 100644 --- a/sys/hps_io.sv +++ b/sys/hps_io.sv @@ -226,14 +226,14 @@ video_calc video_calc .new_vmode(new_vmode), .video_rotated(video_rotated), - .par_num(byte_cnt[3:0]), + .par_num(byte_cnt[4:0]), .dout(vc_dout) ); ///////////////////////////////////////////////////////// localparam STRLEN = $size(CONF_STR)>>3; -localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1; +localparam MAX_W = $clog2((64 > (STRLEN+2)) ? 64 : (STRLEN+2))-1; wire [7:0] conf_byte; generate @@ -502,7 +502,7 @@ always@(posedge clk_sys) begin : uio_block 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout; + 'h23: if(!byte_cnt[MAX_W:5]) io_dout <= vc_dout; //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; @@ -872,7 +872,7 @@ module video_calc input new_vmode, input video_rotated, - input [3:0] par_num, + input [4:0] par_num, output reg [15:0] dout ); @@ -893,6 +893,9 @@ always @(posedge clk_sys) begin 13: dout <= vid_vtime_hdmi[31:16]; 14: dout <= vid_ccnt[15:0]; 15: dout <= vid_ccnt[31:16]; + 16: dout <= vid_pixrep; + 17: dout <= vid_de_h; + 18: dout <= vid_de_v; default dout <= 0; endcase end @@ -902,24 +905,44 @@ reg [31:0] vid_vcnt = 0; reg [31:0] vid_ccnt = 0; reg [7:0] vid_nres = 0; reg [1:0] vid_int = 0; +reg [7:0] vid_pixrep; +reg [15:0] vid_de_h; +reg [7:0] vid_de_v; always @(posedge clk_vid) begin integer hcnt; integer vcnt; integer ccnt; - reg old_vs= 0, old_de = 0, old_vmode = 0; + reg [7:0] pcnt; + reg [7:0] de_v; + reg [15:0] de_h; + reg old_vs = 0, old_hs = 0, old_hs_vclk = 0, old_de = 0, old_de_vclk = 0, old_de1 = 0, old_vmode = 0; reg [3:0] resto = 0; reg calch = 0; if(calch & de) ccnt <= ccnt + 1; + pcnt <= pcnt + 1'd1; + + old_hs_vclk <= hs; + de_h <= de_h + 1'd1; + if(old_hs_vclk & ~hs) de_h <= 1; + + old_de_vclk <= de; + if(calch & ~old_de_vclk & de) vid_de_h <= de_h; if(ce_pix) begin old_vs <= vs; + old_hs <= hs; old_de <= de; + old_de1 <= old_de; + pcnt <= 1; if(~vs & ~old_de & de) vcnt <= vcnt + 1; if(calch & de) hcnt <= hcnt + 1; if(old_de & ~de) calch <= 0; + if(~old_de1 & old_de) vid_pixrep <= pcnt; + if(old_hs & ~hs) de_v <= de_v + 1'd1; + if(calch & ~old_de & de) vid_de_v <= de_v; if(old_vs & ~vs) begin vid_int <= {vid_int[0],f1}; @@ -939,6 +962,7 @@ always @(posedge clk_vid) begin hcnt <= 0; ccnt <= 0; calch <= 1; + de_v <= 0; end end end diff --git a/sys/mcp23009.sv b/sys/mcp23009.sv index 40cbf5e..82eaf37 100644 --- a/sys/mcp23009.sv +++ b/sys/mcp23009.sv @@ -8,10 +8,12 @@ module mcp23009 output reg [2:0] btn, input [2:0] led, - output reg sd_cd, + output reg flg_sd_cd, + output reg flg_present, + output reg flg_mode, - output scl, - inout sda + output scl, + inout sda ); @@ -50,7 +52,9 @@ always@(posedge clk) begin idx <= 0; btn <= 0; rw <= 0; - sd_cd <= 1; + flg_sd_cd <= 1; + flg_present <= 0; + flg_mode <= 1; end else begin if(~&init_data[idx]) begin @@ -84,7 +88,10 @@ always@(posedge clk) begin state <= 0; rw <= 0; if(!error) begin - if(rw) {sd_cd, btn} <= {dout[7], dout[5:3]}; + if(rw) begin + {flg_sd_cd, flg_mode, btn} <= {dout[7:3]}; + flg_present <= 1; + end rw <= ~rw; end end diff --git a/sys/pll_cfg.qip b/sys/pll_cfg.qip index c3394be..0b560f9 100644 --- a/sys/pll_cfg.qip +++ b/sys/pll_cfg.qip @@ -1,44 +1,5 @@ -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" -set_global_assignment -library "pll_cfg" -name MISC_FILE [file join $::quartus(qip_path) "pll_cfg.cmp"] -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_QSYS_MODE "UNKNOWN" set_global_assignment -name SYNTHESIS_ONLY_QIP ON -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_NAME "cGxsX2hkbWlfY2Zn" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" -set_global_assignment -entity "pll_cfg" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_NAME "YWx0ZXJhX3BsbF9yZWNvbmZpZ190b3A=" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTCBSZWNvbmZpZw==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_REPORT_HIERARCHY "Off" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_INTERNAL "Off" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_VERSION "MTcuMA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIFJlY29uZmlndXJhdGlvbiBCbG9jayhBTFRFUkFfUExMX1JFQ09ORklHKQ==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "ZGV2aWNlX2ZhbWlseQ==::Q3ljbG9uZSBW::ZGV2aWNlX2ZhbWlseQ==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX01JRg==::ZmFsc2U=::RW5hYmxlIE1JRiBTdHJlYW1pbmc=" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0JZVEVFTkFCTEU=::ZmFsc2U=::QWRkIGJ5dGVlbmFibGUgcG9ydA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "QllURUVOQUJMRV9XSURUSA==::NA==::QllURUVOQUJMRV9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfQUREUl9XSURUSA==::Ng==::UkVDT05GSUdfQUREUl9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "UkVDT05GSUdfREFUQV9XSURUSA==::MzI=::UkVDT05GSUdfREFUQV9XSURUSA==" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "cmVjb25mX3dpZHRo::NjQ=::cmVjb25mX3dpZHRo" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_COMPONENT_PARAMETER "V0FJVF9GT1JfTE9DSw==::dHJ1ZQ==::V0FJVF9GT1JfTE9DSw==" - -set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg_hdmi.v"] set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"] set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"] - -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_NAME "altera_pll_reconfig" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_VERSION "17.0" -set_global_assignment -entity "altera_pll_reconfig_top" -library "pll_cfg" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_cfg/altera_pll_reconfig_core.v b/sys/pll_cfg/altera_pll_reconfig_core.v index 4bc1fbb..a9e2b8c 100644 --- a/sys/pll_cfg/altera_pll_reconfig_core.v +++ b/sys/pll_cfg/altera_pll_reconfig_core.v @@ -16,7 +16,7 @@ module altera_pll_reconfig_core #( parameter reconf_width = 64, - parameter device_family = "Stratix V", + parameter device_family = "Cyclone V", // MIF Streaming parameters parameter RECONFIG_ADDR_WIDTH = 6, parameter RECONFIG_DATA_WIDTH = 32, @@ -1883,7 +1883,7 @@ module fpll_dprio_init ( endmodule module dyn_phase_shift #( - parameter device_family = "Stratix V" + parameter device_family = "Cyclone V" ) ( input wire clk, @@ -2112,7 +2112,7 @@ endmodule module generic_lcell_comb #( //parameter - parameter family = "Stratix V", + parameter family = "Cyclone V", parameter lut_mask = 64'hAAAAAAAAAAAAAAAA, parameter dont_touch = "on" ) ( diff --git a/sys/pll_cfg/altera_pll_reconfig_top.v b/sys/pll_cfg/altera_pll_reconfig_top.v index c1bfa8b..843c970 100644 --- a/sys/pll_cfg/altera_pll_reconfig_top.v +++ b/sys/pll_cfg/altera_pll_reconfig_top.v @@ -16,7 +16,7 @@ module altera_pll_reconfig_top #( parameter reconf_width = 64, - parameter device_family = "Stratix V", + parameter device_family = "Cyclone V", parameter RECONFIG_ADDR_WIDTH = 6, parameter RECONFIG_DATA_WIDTH = 32, diff --git a/sys/pll_cfg.v b/sys/pll_cfg/pll_cfg.v similarity index 100% rename from sys/pll_cfg.v rename to sys/pll_cfg/pll_cfg.v diff --git a/sys/pll_cfg/pll_cfg_hdmi.v b/sys/pll_cfg/pll_cfg_hdmi.v new file mode 100644 index 0000000..1912c2a --- /dev/null +++ b/sys/pll_cfg/pll_cfg_hdmi.v @@ -0,0 +1,1282 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + +// original file was altera_pll_reconfig_core.v +// not needed functionality was cut out to reduce ressource consumption + +module pll_cfg_hdmi +#( + parameter reconf_width = 64, + parameter device_family = "Cyclone V" +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire mgmt_waitrequest, + input wire [5:0] mgmt_address, + input wire mgmt_write, + input wire [31:0] mgmt_writedata +); + localparam mode_WR = 1'b0; + localparam MODE_REG = 6'b000000; + localparam START_REG = 6'b000010; + localparam N_REG = 6'b000011; + localparam M_REG = 6'b000100; + localparam C_COUNTERS_REG = 6'b000101; + //localparam DPS_REG = 6'b000110; // unused + localparam DSM_REG = 6'b000111; + localparam BWCTRL_REG = 6'b001000; + localparam CP_CURRENT_REG = 6'b001001; + //localparam ANY_DPRIO = 6'b100000; // unused + //localparam CNT_BASE = 5'b001010; // unused + //localparam VCO_REG = 6'b011100; // unused + + //C Counters + localparam number_of_counters = 5'd6; + //C counter addresses + localparam C_CNT_0_DIV_ADDR = 5'h00; + localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11; + localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15; + localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17; + localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14; + localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16; + //N counter addresses + localparam N_CNT_DIV_ADDR = 5'h13; + localparam N_CNT_BYPASS_EN_ADDR = 5'h15; + localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17; + //M counter addresses + localparam M_CNT_DIV_ADDR = 5'h12; + localparam M_CNT_BYPASS_EN_ADDR = 5'h15; + localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17; + + //DSM address + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18; + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19; + localparam DSM_K_READY_ADDR = 5'h17; + localparam DSM_K_DITHER_ADDR = 5'h17; + localparam DSM_OUT_SEL_ADDR = 6'h30; + + //Other DSM params + localparam DSM_K_READY_BIT_INDEX = 4'd11; + //BWCTRL address + //Bit 0-3 of addr + localparam BWCTRL_ADDR = 6'h30; + //CP_CURRENT address + //Bit 0-2 of addr + localparam CP_CURRENT_ADDR = 6'h31; + + // VCODIV address + localparam VCO_ADDR = 5'h17; + + localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4, + FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10, + ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15; + localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10; + + wire clk; + wire reset; + wire gnd; + + wire [5: 0] slave_address; + wire slave_write; + wire [31: 0] slave_writedata; + + wire slave_waitrequest; + reg slave_mode; + + assign clk = mgmt_clk; + + assign slave_address = mgmt_address; + assign slave_write = mgmt_write; + assign slave_writedata = mgmt_writedata; + + // Outputs + assign mgmt_waitrequest = slave_waitrequest; //Read waitrequest asserted in polling mode + + //internal signals + wire locked_orig; + wire locked; + + wire pll_start; + wire pll_start_valid; + + wire pll_start_asserted; + + reg [1:0] current_state; + reg [1:0] next_state; + + reg status;//0=busy, 1=ready + //user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load); + //declaring the init wires. These will have 0 on them for 64 clk cycles + wire [ 5:0] init_dprio_address; + wire init_dprio_read; + wire [ 1:0] init_dprio_byteen; + wire init_dprio_write; + wire [15:0] init_dprio_writedata; + + wire init_atpgmode; + wire init_mdio_dis; + wire init_scanen; + wire init_ser_shift_load; + wire dprio_init_done; + + //DPRIO output signals after initialization is done + wire dprio_clk; + reg avmm_dprio_write; + reg avmm_dprio_read; + reg [5:0] avmm_dprio_address; + reg [15:0] avmm_dprio_writedata; + reg [1:0] avmm_dprio_byteen; + wire avmm_atpgmode; + wire avmm_mdio_dis; + wire avmm_scanen; + + //Final output wires that are muxed between the init and avmm wires. + wire dprio_init_reset; + wire [5:0] dprio_address /*synthesis keep*/; + wire dprio_read/*synthesis keep*/; + wire [1:0] dprio_byteen/*synthesis keep*/; + wire dprio_write/*synthesis keep*/; + wire [15:0] dprio_writedata/*synthesis keep*/; + wire dprio_mdio_dis/*synthesis keep*/; + wire dprio_ser_shift_load/*synthesis keep*/; + wire dprio_atpgmode/*synthesis keep*/; + wire dprio_scanen/*synthesis keep*/; + + + //other PLL signals for dyn ph shift + wire phase_done/*synthesis keep*/; + wire phase_en/*synthesis keep*/; + wire up_dn/*synthesis keep*/; + wire [4:0] cnt_sel; + + //DPRIO input signals + wire [15:0] dprio_readdata; + + //internal logic signals + //storage registers for user sent data + reg dprio_temp_read_1; + reg dprio_temp_read_2; + reg dprio_start; + wire usr_valid_changes; + reg [3:0] dprio_cur_state; + reg [3:0] dprio_next_state; + reg [15:0] dprio_temp_m_n_c_readdata_1_d; + reg [15:0] dprio_temp_m_n_c_readdata_2_d; + reg [15:0] dprio_temp_m_n_c_readdata_1_q; + reg [15:0] dprio_temp_m_n_c_readdata_2_q; + reg dprio_write_done; + //C counters signals + reg [7:0] usr_c_cnt_lo; + reg [7:0] usr_c_cnt_hi; + reg usr_c_cnt_bypass_en; + reg usr_c_cnt_odd_duty_div_en; + reg temp_c_cnt_bypass_en [0:17]; + reg temp_c_cnt_odd_duty_div_en [0:17]; + reg any_c_cnt_changed; + reg all_c_cnt_done_q; + reg all_c_cnt_done_d; + reg [17:0] c_cnt_changed; + reg [17:0] c_cnt_done_d; + reg [17:0] c_cnt_done_q; + //N counter signals + reg [7:0] usr_n_cnt_lo; + reg [7:0] usr_n_cnt_hi; + reg usr_n_cnt_bypass_en; + reg usr_n_cnt_odd_duty_div_en; + reg n_cnt_changed; + reg n_cnt_done_d; + reg n_cnt_done_q; + //M counter signals + reg [7:0] usr_m_cnt_lo; + reg [7:0] usr_m_cnt_hi; + reg usr_m_cnt_bypass_en; + reg usr_m_cnt_odd_duty_div_en; + reg m_cnt_changed; + reg m_cnt_done_d; + reg m_cnt_done_q; + //dyn phase regs + reg [15:0] usr_num_shifts; + reg [4:0] usr_cnt_sel /*synthesis preserve*/; + reg usr_up_dn; + reg dps_changed; + wire dps_changed_valid; + wire dps_done; + + //DSM Signals + reg [31:0] usr_k_value; + reg dsm_k_changed; + reg dsm_k_done_d; + reg dsm_k_done_q; + reg dsm_k_ready_false_done_d; + //BW signals + reg [3:0] usr_bwctrl_value; + reg bwctrl_changed; + reg bwctrl_done_d; + reg bwctrl_done_q; + //CP signals + reg [2:0] usr_cp_current_value; + reg cp_current_changed; + reg cp_current_done_d; + reg cp_current_done_q; + //VCO signals + reg usr_vco_value; + reg vco_changed; + reg vco_done_d; + reg vco_done_q; + //Manual DPRIO signals + reg manual_dprio_done_q; + reg manual_dprio_done_d; + reg manual_dprio_changed; + reg [5:0] usr_dprio_address; + reg [15:0] usr_dprio_writedata_0; + reg usr_r_w; + //keeping track of which operation happened last + reg [5:0] operation_address; + // Address wires for all C_counter DPRIO registers + // These are outputs of LUTS, changing depending + // on whether PLL_0 or PLL_1 being used + + + //Fitter will tell if FPLL1 is being used + wire fpll_1; + + // MAIN FSM + + // Synchronize locked signal + altera_std_synchronizer #( + .depth(3) + ) altera_std_synchronizer_inst ( + .clk(mgmt_clk), + .reset_n(~mgmt_reset), + .din(locked_orig), + .dout(locked) + ); + + always @(posedge clk) + begin + if (reset) + begin + dprio_cur_state <= DPRIO_IDLE; + current_state <= IDLE; + end + else + begin + current_state <= next_state; + dprio_cur_state <= dprio_next_state; + end + end + + always @(*) + begin + case(current_state) + IDLE: + begin + if (pll_start & !slave_waitrequest & usr_valid_changes) + next_state = WAIT_ON_LOCK; + else + next_state = IDLE; + end + WAIT_ON_LOCK: + begin + if (locked & dps_done & dprio_write_done) // received locked high from PLL + begin + if (slave_mode==mode_WR) //if the mode is waitrequest, then + // goto IDLE state directly + next_state = IDLE; + else + next_state = LOCKED; //otherwise go the locked state + end + else + next_state = WAIT_ON_LOCK; + end + + LOCKED: + begin + next_state = LOCKED; + end + + default: next_state = 2'bxx; + + endcase + end + + + // ask the pll to start reconfig + assign pll_start = (pll_start_asserted & (current_state==IDLE)) ; + assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ; + + + + // WRITE OPERATIONS + assign pll_start_asserted = slave_write & (slave_address == START_REG); + + //reading the mode register to determine what mode the slave will operate + //in. + always @(posedge clk) + begin + if (reset) + slave_mode <= mode_WR; + else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest) + slave_mode <= slave_writedata[0]; + end + + //record which values user wants to change. + + //reading in the actual values that need to be reconfigged and sending + //them to the PLL + always @(posedge clk) + begin + if (reset) + begin + //reset all regs here + //BW signals reset + usr_bwctrl_value <= 0; + bwctrl_changed <= 0; + bwctrl_done_q <= 0; + //CP signals reset + usr_cp_current_value <= 0; + cp_current_changed <= 0; + cp_current_done_q <= 0; + //VCO signals reset + usr_vco_value <= 0; + vco_changed <= 0; + vco_done_q <= 0; + //DSM signals reset + usr_k_value <= 0; + dsm_k_changed <= 0; + dsm_k_done_q <= 0; + //N counter signals reset + usr_n_cnt_lo <= 0; + usr_n_cnt_hi <= 0; + usr_n_cnt_bypass_en <= 0; + usr_n_cnt_odd_duty_div_en <= 0; + n_cnt_changed <= 0; + n_cnt_done_q <= 0; + //M counter signals reset + usr_m_cnt_lo <= 0; + usr_m_cnt_hi <= 0; + usr_m_cnt_bypass_en <= 0; + usr_m_cnt_odd_duty_div_en <= 0; + m_cnt_changed <= 0; + m_cnt_done_q <= 0; + //C counter signals reset + usr_c_cnt_lo <= 0; + usr_c_cnt_hi <= 0; + usr_c_cnt_bypass_en <= 0; + usr_c_cnt_odd_duty_div_en <= 0; + any_c_cnt_changed <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + //generic signals + dprio_start <= 0; + dprio_temp_m_n_c_readdata_1_q <= 0; + dprio_temp_m_n_c_readdata_2_q <= 0; + c_cnt_done_q <= 0; + //DPS signals + usr_up_dn <= 0; + usr_cnt_sel <= 0; + usr_num_shifts <= 0; + dps_changed <= 0; + //manual DPRIO signals + manual_dprio_changed <= 0; + usr_dprio_address <= 0; + usr_dprio_writedata_0 <= 0; + usr_r_w <= 0; + operation_address <= 0; + end + else + begin + if (dprio_temp_read_1) + begin + dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d; + end + if (dprio_temp_read_2) + begin + dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d; + end + if ((dps_done)) dps_changed <= 0; + if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d; + if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d; + if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d; + if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d; + if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d; + if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d; + if (cp_current_done_d) cp_current_done_q <= cp_current_done_d; + if (vco_done_d) vco_done_q <= vco_done_d; + if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d; + + if (dprio_next_state == ONE) + dprio_start <= 0; + if (dprio_write_done) + begin + bwctrl_done_q <= 0; + cp_current_done_q <= 0; + vco_done_q <= 0; + dsm_k_done_q <= 0; + dsm_k_done_q <= 0; + n_cnt_done_q <= 0; + m_cnt_done_q <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + dsm_k_changed <= 0; + n_cnt_changed <= 0; + m_cnt_changed <= 0; + any_c_cnt_changed <= 0; + bwctrl_changed <= 0; + cp_current_changed <= 0; + vco_changed <= 0; + manual_dprio_changed <= 0; + manual_dprio_done_q <= 0; + + end + else + begin + dsm_k_changed <= dsm_k_changed; + n_cnt_changed <= n_cnt_changed; + m_cnt_changed <= m_cnt_changed; + any_c_cnt_changed <= any_c_cnt_changed; + manual_dprio_changed <= manual_dprio_changed; + end + + + if(slave_write & !slave_waitrequest) + begin + case(slave_address) + //read in the values here from the user and act on them + DSM_REG: + begin + operation_address <= DSM_REG; + usr_k_value <= slave_writedata[31:0]; + dsm_k_changed <= 1'b1; + dsm_k_done_q <= 0; + dprio_start <= 1'b1; + end + N_REG: + begin + operation_address <= N_REG; + usr_n_cnt_lo <= slave_writedata[7:0]; + usr_n_cnt_hi <= slave_writedata[15:8]; + usr_n_cnt_bypass_en <= slave_writedata[16]; + usr_n_cnt_odd_duty_div_en <= slave_writedata[17]; + n_cnt_changed <= 1'b1; + n_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + M_REG: + begin + operation_address <= M_REG; + usr_m_cnt_lo <= slave_writedata[7:0]; + usr_m_cnt_hi <= slave_writedata[15:8]; + usr_m_cnt_bypass_en <= slave_writedata[16]; + usr_m_cnt_odd_duty_div_en <= slave_writedata[17]; + m_cnt_changed <= 1'b1; + m_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + //DPS_REG: + //begin + // operation_address <= DPS_REG; + // usr_num_shifts <= slave_writedata[15:0]; + // usr_up_dn <= slave_writedata[21]; + // dps_changed <= 1; + //end + C_COUNTERS_REG: + begin + operation_address <= C_COUNTERS_REG; + usr_c_cnt_lo <= slave_writedata[7:0]; + usr_c_cnt_hi <= slave_writedata[15:8]; + usr_c_cnt_bypass_en <= slave_writedata[16]; + usr_c_cnt_odd_duty_div_en <= slave_writedata[17]; + any_c_cnt_changed <= 1'b1; + all_c_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + BWCTRL_REG: + begin + usr_bwctrl_value <= slave_writedata[3:0]; + bwctrl_changed <= 1'b1; + bwctrl_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= BWCTRL_REG; + end + CP_CURRENT_REG: + begin + usr_cp_current_value <= slave_writedata[2:0]; + cp_current_changed <= 1'b1; + cp_current_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= CP_CURRENT_REG; + end + //VCO_REG: + //begin + // usr_vco_value <= slave_writedata[0]; + // vco_changed <= 1'b1; + // vco_done_q <= 0; + // dprio_start <= 1'b1; + // operation_address <= VCO_REG; + //end + //ANY_DPRIO: + //begin + // operation_address <= ANY_DPRIO; + // manual_dprio_changed <= 1'b1; + // usr_dprio_address <= slave_writedata[5:0]; + // usr_dprio_writedata_0 <= slave_writedata[21:6]; + // usr_r_w <= slave_writedata[22]; + // manual_dprio_done_q <= 0; + // dprio_start <= 1'b1; + //end + endcase + end + end + end + //C Counter assigning values to the 2-d array of values for each C counter + + reg [4:0] j; + always @(posedge clk) + begin + + if (reset) + begin + c_cnt_changed[17:0] <= 0; + for (j = 0; j < number_of_counters; j = j + 1'b1) + begin : c_cnt_reset + temp_c_cnt_bypass_en[j] <= 0; + temp_c_cnt_odd_duty_div_en[j] <= 0; + end + end + else + begin + if (dprio_write_done) + begin + c_cnt_changed <= 0; + end + if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG)) + begin + temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [5] <= 1'b1; + end + end + end + + + //logic to handle which writes the user indicated and wants to start. + assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed; + + + //start the reconfig operations by writing to the DPRIO + reg break_loop; + reg [4:0] i; + always @(*) + begin + dprio_temp_read_1 = 0; + dprio_temp_read_2 = 0; + dprio_temp_m_n_c_readdata_1_d = 0; + dprio_temp_m_n_c_readdata_2_d = 0; + break_loop = 0; + dprio_next_state = DPRIO_IDLE; + avmm_dprio_write = 0; + avmm_dprio_read = 0; + avmm_dprio_address = 0; + avmm_dprio_writedata = 0; + avmm_dprio_byteen = 0; + dprio_write_done = 1; + manual_dprio_done_d = 0; + n_cnt_done_d = 0; + dsm_k_done_d = 0; + dsm_k_ready_false_done_d = 0; + m_cnt_done_d = 0; + c_cnt_done_d[17:0] = 0; + all_c_cnt_done_d = 0; + bwctrl_done_d = 0; + cp_current_done_d = 0; + vco_done_d = 0; + i = 0; + + // Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes) + if (dprio_start) + dprio_write_done = 0; + + if (current_state == WAIT_ON_LOCK) + begin + case (dprio_cur_state) + ONE: + begin + if (n_cnt_changed & !n_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = N_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_n_cnt_lo; + avmm_dprio_writedata[15:8] = usr_n_cnt_hi; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = M_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_m_cnt_lo; + avmm_dprio_writedata[15:8] = usr_m_cnt_hi; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_hilo + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i; + else avmm_dprio_address = C_CNT_0_DIV_ADDR + i; + avmm_dprio_writedata[7:0] = usr_c_cnt_lo; + avmm_dprio_writedata[15:8] = usr_c_cnt_hi; + //To break from the loop, since only one counter + //is addressed at a time + break_loop = 1'b1; + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (cp_current_changed & !cp_current_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (vco_changed & !vco_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_write = usr_r_w; + avmm_dprio_address = usr_dprio_address; + avmm_dprio_writedata[15:0] = usr_dprio_writedata_0; + end + else dprio_next_state = DPRIO_IDLE; + end + + TWO: + begin + //handle reading the two setting bits on n_cnt, then + //writing them back while preserving other bits. + //Issue two consecutive reads then wait; readLatency=3 + dprio_write_done = 0; + dprio_next_state = THREE; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + //reading the K ready 16 bit word. Need to write 0 to it + //afterwards to indicate that K has not been done writing + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + dprio_next_state = FOUR; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + dprio_next_state = FOUR; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + dprio_next_state = FOUR; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + dprio_next_state = FOUR; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + avmm_dprio_read = ~usr_r_w; + avmm_dprio_address = usr_dprio_address; + dprio_next_state = DPRIO_DONE; + end + else dprio_next_state = DPRIO_IDLE; + end + THREE: + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + dprio_next_state = FOUR; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + else dprio_next_state = DPRIO_IDLE; + end + FOUR: + begin + dprio_temp_read_1 = 1'b1; + dprio_write_done = 0; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + dprio_temp_m_n_c_readdata_1_d = dprio_readdata; + dprio_next_state = FIVE; + end + else dprio_next_state = DPRIO_IDLE; + end + FIVE: + begin + dprio_write_done = 0; + dprio_temp_read_2 = 1'b1; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + //this is where DSM ready value comes. + //Need to store in a register to be used later + dprio_temp_m_n_c_readdata_2_d = dprio_readdata; + dprio_next_state = SIX; + end + else dprio_next_state = DPRIO_IDLE; + end + SIX: + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = SEVEN; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_bypass_en; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_bypass_en; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_write = 0; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_write = 0; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_write = 0; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_write = 0; + end + else dprio_next_state = DPRIO_IDLE; + end + SEVEN: + begin + dprio_write_done = 0; + dprio_next_state = EIGHT; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en; + n_cnt_done_d = 1'b1; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en; + m_cnt_done_d = 1'b1; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0; + dsm_k_ready_false_done_d = 1'b1; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + avmm_dprio_writedata[3:0] = usr_bwctrl_value; + bwctrl_done_d = 1'b1; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + avmm_dprio_writedata[2:0] = usr_cp_current_value; + cp_current_done_d = 1'b1; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + avmm_dprio_writedata[8] = usr_vco_value; + vco_done_d = 1'b1; + end + + + //if all C_cnt that were changed are done, then assert all_c_cnt_done + if (c_cnt_done_d == c_cnt_changed) + all_c_cnt_done_d = 1'b1; + if (n_cnt_changed & n_cnt_done_d) + dprio_next_state = DPRIO_DONE; + if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q) + dprio_next_state = ONE; + else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q) + dprio_next_state = ONE; + else if (dsm_k_changed & !dsm_k_ready_false_done_d) + dprio_next_state = TWO; + else if (dsm_k_changed & !dsm_k_done_q) + dprio_next_state = EIGHT; + else if (bwctrl_changed & !bwctrl_done_d) + dprio_next_state = TWO; + else if (cp_current_changed & !cp_current_done_d) + dprio_next_state = TWO; + else if (vco_changed & !vco_done_d) + dprio_next_state = TWO; + else + begin + dprio_next_state = DPRIO_DONE; + dprio_write_done = 1'b1; + end + end + //finish the rest of the DSM reads/writes + //writing k value, writing k_ready to 1. + EIGHT: + begin + dprio_write_done = 0; + dprio_next_state = NINE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0; + avmm_dprio_writedata[15:0] = usr_k_value[15:0]; + end + end + NINE: + begin + dprio_write_done = 0; + dprio_next_state = TEN; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1; + avmm_dprio_writedata[15:0] = usr_k_value[31:16]; + end + end + TEN: + begin + dprio_write_done = 0; + dprio_next_state = ONE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + //already have the readdata for DSM_K_READY_ADDR since we read it + //earlier. Just reuse here + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1; + dsm_k_done_d = 1'b1; + end + end + DPRIO_DONE: + begin + dprio_write_done = 1'b1; + if (dprio_start) dprio_next_state = DPRIO_IDLE; + else dprio_next_state = DPRIO_DONE; + end + DPRIO_IDLE: + begin + if (dprio_start) dprio_next_state = ONE; + else dprio_next_state = DPRIO_IDLE; + end + default: dprio_next_state = 4'bxxxx; + endcase + end + + end + + + //assert the waitreq signal according to the state of the slave + assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0; + + + dyn_phase_shift dyn_phase_shift_inst ( + .clk(clk), + .reset(reset), + .phase_done(phase_done), + .pll_start_valid(pll_start_valid), + .dps_changed(dps_changed), + .dps_changed_valid(dps_changed_valid), + .dprio_write_done(dprio_write_done), + .usr_num_shifts(usr_num_shifts), + .usr_cnt_sel(usr_cnt_sel), + .usr_up_dn(usr_up_dn), + .locked(locked), + .dps_done(dps_done), + .phase_en(phase_en), + .up_dn(up_dn), + .cnt_sel(cnt_sel)); + defparam dyn_phase_shift_inst.device_family = device_family; + + assign dprio_clk = clk; + self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset); + + dprio_mux dprio_mux_inst ( + .init_dprio_address(init_dprio_address), + .init_dprio_read(init_dprio_read), + .init_dprio_byteen(init_dprio_byteen), + .init_dprio_write(init_dprio_write), + .init_dprio_writedata(init_dprio_writedata), + + + .init_atpgmode(init_atpgmode), + .init_mdio_dis(init_mdio_dis), + .init_scanen(init_scanen), + .init_ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done), + + // Inputs from avmm master + .avmm_dprio_address(avmm_dprio_address), + .avmm_dprio_read(avmm_dprio_read), + .avmm_dprio_byteen(avmm_dprio_byteen), + .avmm_dprio_write(avmm_dprio_write), + .avmm_dprio_writedata(avmm_dprio_writedata), + + .avmm_atpgmode(avmm_atpgmode), + .avmm_mdio_dis(avmm_mdio_dis), + .avmm_scanen(avmm_scanen), + + // Outputs to fpll + .dprio_address(dprio_address), + .dprio_read(dprio_read), + .dprio_byteen(dprio_byteen), + .dprio_write(dprio_write), + .dprio_writedata(dprio_writedata), + + .atpgmode(dprio_atpgmode), + .mdio_dis(dprio_mdio_dis), + .scanen(dprio_scanen), + .ser_shift_load(dprio_ser_shift_load) + ); + + + fpll_dprio_init fpll_dprio_init_inst ( + .clk(clk), + .reset_n(~reset), + .locked(locked), + + //outputs + .dprio_address(init_dprio_address), + .dprio_read(init_dprio_read), + .dprio_byteen(init_dprio_byteen), + .dprio_write(init_dprio_write), + .dprio_writedata(init_dprio_writedata), + + .atpgmode(init_atpgmode), + .mdio_dis(init_mdio_dis), + .scanen(init_scanen), + .ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done)); + + //address luts, to be reconfigged by the Fitter + //FPLL_1 or 0 address lut + generic_lcell_comb lcell_fpll_0_1 ( + .dataa(1'b0), + .combout (fpll_1)); + defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_fpll_0_1.dont_touch = "on"; + defparam lcell_fpll_0_1.family = device_family; + + + wire dprio_read_combout; + generic_lcell_comb lcell_dprio_read ( + .dataa(fpll_1), + .datab(dprio_read), + .datac(1'b0), + .datad(1'b0), + .datae(1'b0), + .dataf(1'b0), + .combout (dprio_read_combout)); + defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_dprio_read.dont_touch = "on"; + defparam lcell_dprio_read.family = device_family; + + + + + + //assign reconfig_to_pll signals + assign reconfig_to_pll[0] = dprio_clk; + assign reconfig_to_pll[1] = ~dprio_init_reset; + assign reconfig_to_pll[2] = dprio_write; + assign reconfig_to_pll[3] = dprio_read_combout; + assign reconfig_to_pll[9:4] = dprio_address; + assign reconfig_to_pll[25:10] = dprio_writedata; + assign reconfig_to_pll[27:26] = dprio_byteen; + assign reconfig_to_pll[28] = dprio_ser_shift_load; + assign reconfig_to_pll[29] = dprio_mdio_dis; + assign reconfig_to_pll[30] = phase_en; + assign reconfig_to_pll[31] = up_dn; + assign reconfig_to_pll[36:32] = cnt_sel; + assign reconfig_to_pll[37] = dprio_scanen; + assign reconfig_to_pll[38] = dprio_atpgmode; + //assign reconfig_to_pll[40:37] = clken; + assign reconfig_to_pll[63:39] = 0; + + //assign reconfig_from_pll signals + assign dprio_readdata = reconfig_from_pll [15:0]; + assign locked_orig = reconfig_from_pll [16]; + assign phase_done = reconfig_from_pll [17]; + +endmodule diff --git a/sys/pll_q13.qip b/sys/pll_q13.qip index 13a7ed4..78e7e40 100644 --- a/sys/pll_q13.qip +++ b/sys/pll_q13.qip @@ -1,6 +1,4 @@ set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.13.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.13.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.13.qip ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg.v ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_core.v ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_cfg/altera_pll_reconfig_top.v ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] diff --git a/sys/sys.tcl b/sys/sys.tcl index ce83683..93b6247 100644 --- a/sys/sys.tcl +++ b/sys/sys.tcl @@ -16,13 +16,6 @@ set_location_assignment PIN_V10 -to ADC_SCK set_location_assignment PIN_AC4 -to ADC_SDI set_location_assignment PIN_AD4 -to ADC_SDO -#============================================================ -# ARDUINO -#============================================================ -set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[*] -set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to ARDUINO_IO[*] -set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to ARDUINO_IO[*] - #============================================================ # I2C LEDS/BUTTONS #============================================================ diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 0d8763f..ac21334 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -25,6 +25,7 @@ set_false_path -from [get_ports {KEY*}] set_false_path -from [get_ports {BTN_*}] set_false_path -to [get_ports {LED_*}] set_false_path -to [get_ports {VGA_*}] +set_false_path -from [get_ports {VGA_EN}] set_false_path -to [get_ports {AUDIO_SPDIF}] set_false_path -to [get_ports {AUDIO_L}] set_false_path -to [get_ports {AUDIO_R}] @@ -34,6 +35,7 @@ set_false_path -from {cfg[*]} set_false_path -from {VSET[*]} set_false_path -to {wcalc[*] hcalc[*]} set_false_path -to {hdmi_width[*] hdmi_height[*]} +set_false_path -to {deb_* btn_en btn_up} set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 @@ -58,6 +60,7 @@ set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {aflt_* acx* acy* areset* arc*} set_false_path -from {arx* ary*} set_false_path -from {vs_line*} +set_false_path -from {ColorBurst_Range* PhaseInc* pal_en cvbs yc_en} set_false_path -from {ascal|o_ihsize*} set_false_path -from {ascal|o_ivsize*} @@ -70,4 +73,5 @@ set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} set_false_path -from {ascal|o_hsize* ascal|o_vsize*} -set_false_path -from {mcp23009|sd_cd} +set_false_path -from {mcp23009|flg_*} +set_false_path -to {sysmem|fpga_interfaces|clocks_resets*} diff --git a/sys/sys_top.v b/sys/sys_top.v index 55619db..65129eb 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -72,7 +72,7 @@ module sys_top output [5:0] VGA_R, output [5:0] VGA_G, output [5:0] VGA_B, - inout VGA_HS, // VGA_HS is secondary SD card detect when VGA_EN = 1 (inactive) + inout VGA_HS, output VGA_VS, input VGA_EN, // active low @@ -125,27 +125,22 @@ module sys_top ); ////////////////////// Secondary SD /////////////////////////////////// -wire SD_CS, SD_CLK, SD_MOSI; +wire SD_CS, SD_CLK, SD_MOSI, SD_MISO, SD_CD; `ifndef MISTER_DUAL_SDRAM - wire sd_miso = SW[3] | SDIO_DAT[0]; + assign SD_CD = mcp_en ? mcp_sdcd : SDCD_SPDIF; + assign SD_MISO = SD_CD | (mcp_en ? SD_SPI_MISO : (VGA_EN | SDIO_DAT[0])); + assign SD_SPI_CS = mcp_en ? (mcp_sdcd ? 1'bZ : SD_CS) : (sog & ~cs1 & ~VGA_EN) ? 1'b1 : 1'bZ; + assign SD_SPI_CLK = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_CLK; + assign SD_SPI_MOSI = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_MOSI; + assign {SDIO_CLK,SDIO_CMD,SDIO_DAT} = av_dis ? 6'bZZZZZZ : (mcp_en | (SDCD_SPDIF & ~SW[2])) ? {vga_g,vga_r,vga_b} : {SD_CLK,SD_MOSI,SD_CS,3'bZZZ}; `else - wire sd_miso = 1; + assign SD_CD = mcp_sdcd; + assign SD_MISO = mcp_sdcd | SD_SPI_MISO; + assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; + assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; + assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; `endif -wire SD_MISO = mcp_sdcd ? sd_miso : SD_SPI_MISO; - -`ifndef MISTER_DUAL_SDRAM - assign SDIO_DAT[2:1]= 2'bZZ; - assign SDIO_DAT[3] = SW[3] ? 1'bZ : SD_CS; - assign SDIO_CLK = SW[3] ? 1'bZ : SD_CLK; - assign SDIO_CMD = SW[3] ? 1'bZ : SD_MOSI; - assign SD_SPI_CS = mcp_sdcd ? ((~VGA_EN & sog & ~cs1) ? 1'b1 : 1'bZ) : SD_CS; -`else - assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; -`endif - -assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; -assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; ////////////////////// LEDs/Buttons /////////////////////////////////// @@ -157,36 +152,59 @@ wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); wire led_u = ~led_user; wire led_locked; -`ifndef MISTER_DUAL_SDRAM - assign LED_POWER = (SW[3] | led_p) ? 1'bZ : 1'b0; - assign LED_HDD = (SW[3] | led_d) ? 1'bZ : 1'b0; - assign LED_USER = (SW[3] | led_u) ? 1'bZ : 1'b0; -`endif - -//LEDs on main board +//LEDs on de10-nano board assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); -wire btn_r, btn_o, btn_u; -`ifdef MISTER_DUAL_SDRAM - assign {btn_r,btn_o,btn_u} = SW[3] ? {mcp_btn[1],mcp_btn[2],mcp_btn[0]} : ~{SDRAM2_DQ[9],SDRAM2_DQ[13],SDRAM2_DQ[11]}; -`else - assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]}; -`endif - wire [2:0] mcp_btn; wire mcp_sdcd; +wire mcp_en; +wire mcp_mode; mcp23009 mcp23009 ( .clk(FPGA_CLK2_50), .btn(mcp_btn), .led({led_p, led_d, led_u}), - .sd_cd(mcp_sdcd), + .flg_sd_cd(mcp_sdcd), + .flg_present(mcp_en), + .flg_mode(mcp_mode), .scl(IO_SCL), .sda(IO_SDA) ); +wire io_dig = mcp_en ? mcp_mode : SW[3]; + +`ifndef MISTER_DUAL_SDRAM + wire av_dis = io_dig | VGA_EN; + assign LED_POWER = av_dis ? 1'bZ : mcp_en ? de1 : led_p ? 1'bZ : 1'b0; + assign LED_HDD = av_dis ? 1'bZ : mcp_en ? (sog & ~cs1) : led_d ? 1'bZ : 1'b0; + //assign LED_USER = av_dis ? 1'bZ : mcp_en ? ~vga_tx_clk : led_u ? 1'bZ : 1'b0; + assign LED_USER = VGA_TX_CLK; + wire BTN_DIS = VGA_EN; +`else + wire BTN_RESET = SDRAM2_DQ[9]; + wire BTN_OSD = SDRAM2_DQ[13]; + wire BTN_USER = SDRAM2_DQ[11]; + wire BTN_DIS = SDRAM2_DQ[15]; +`endif + +reg BTN_EN = 0; +reg [25:0] btn_timeout = 0; +initial btn_timeout = 0; +always @(posedge FPGA_CLK2_50) begin + reg btn_up = 0; + reg btn_en = 0; + + btn_up <= BTN_RESET & BTN_OSD & BTN_USER; + if(~reset & btn_up & ~&btn_timeout) btn_timeout <= btn_timeout + 1'd1; + btn_en <= ~BTN_DIS; + BTN_EN <= &btn_timeout & btn_en; +end + +wire btn_r = (mcp_en | SW[3]) ? mcp_btn[1] : (BTN_EN & ~BTN_RESET); +wire btn_o = (mcp_en | SW[3]) ? mcp_btn[2] : (BTN_EN & ~BTN_OSD ); +wire btn_u = (mcp_en | SW[3]) ? mcp_btn[0] : (BTN_EN & ~BTN_USER ); reg btn_user, btn_osd; always @(posedge FPGA_CLK2_50) begin @@ -212,7 +230,7 @@ end // gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) // used to avoid lockups while JTAG loading -wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; +wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], io_dig, 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; wire [31:0] gp_out; wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future. @@ -226,7 +244,7 @@ wire io_ss1 = gp_outr[19]; wire io_ss2 = gp_outr[20]; `ifndef MISTER_DEBUG_NOHDMI -wire io_osd_hdmi = io_ss1 & ~io_ss0; + wire io_osd_hdmi = io_ss1 & ~io_ss0; `endif wire io_fpga = ~io_ss1 & io_ss0; @@ -267,14 +285,14 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp reg [15:0] cfg; - reg cfg_set = 0; -wire vga_fb = cfg[12] | vga_force_scaler; `ifdef MISTER_DEBUG_NOHDMI -wire direct_video = 1; + wire vga_fb = 0; + wire direct_video = 1; `else -wire direct_video = cfg[10]; + wire vga_fb = cfg[12] | vga_force_scaler; + wire direct_video = cfg[10]; `endif wire audio_96k = cfg[6]; @@ -283,7 +301,11 @@ wire io_osd_vga = io_ss1 & ~io_ss2; `ifndef MISTER_DUAL_SDRAM wire ypbpr_en = cfg[5]; wire sog = cfg[9]; - wire vga_scaler = cfg[2] | vga_force_scaler; + `ifdef MISTER_DEBUG_NOHDMI + wire vga_scaler = 0; + `else + wire vga_scaler = cfg[2] | vga_force_scaler; + `endif `endif reg cfg_custom_t = 0; @@ -519,17 +541,6 @@ cyclonev_hps_interface_peripheral_uart uart .txd(uart_txd) ); -wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; -cyclonev_hps_interface_peripheral_spi_master spi -( - .sclk_out(aspi_sck), - .txd(aspi_mosi), // mosi - .rxd(aspi_miso), // miso - - .ss_0_n(aspi_ss), - .ss_in_n(1) -); - wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; cyclonev_hps_interface_interrupts interrupts ( @@ -635,11 +646,13 @@ ddr_svc ddr_svc .ram_write(ram2_write), .ram_bcnt(ram2_bcnt), +`ifndef MISTER_DISABLE_ALSA .ch0_addr(alsa_address), .ch0_burst(1), .ch0_data(alsa_readdata), .ch0_req(alsa_req), .ch0_ready(alsa_ready), +`endif .ch1_addr(pal_addr), .ch1_burst(128), @@ -666,120 +679,120 @@ wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd; wire freeze; `ifndef MISTER_DEBUG_NOHDMI -wire clk_hdmi = hdmi_clk_out; - -ascal -#( - .RAMBASE(32'h20000000), -`ifdef MISTER_SMALL_VBUF - .RAMSIZE(32'h00200000), -`else - .RAMSIZE(32'h00800000), -`endif -`ifndef MISTER_FB - .PALETTE2("false"), -`else - `ifndef MISTER_FB_PALETTE + wire clk_hdmi = hdmi_clk_out; + + ascal + #( + .RAMBASE(32'h20000000), + `ifdef MISTER_SMALL_VBUF + .RAMSIZE(32'h00200000), + `else + .RAMSIZE(32'h00800000), + `endif + `ifndef MISTER_FB .PALETTE2("false"), + `else + `ifndef MISTER_FB_PALETTE + .PALETTE2("false"), + `endif `endif -`endif -`ifdef MISTER_DISABLE_ADAPTIVE - .ADAPTIVE("false"), -`endif -`ifdef MISTER_DOWNSCALE_NN - .DOWNSCALE_NN("true"), -`endif - .FRAC(8), - .N_DW(128), - .N_AW(28) -) -ascal -( - .reset_na (~reset_req), - .run (1), - .freeze (freeze), - - .i_clk (clk_ihdmi), - .i_ce (ce_hpix), - .i_r (hr_out), - .i_g (hg_out), - .i_b (hb_out), - .i_hs (hhs_fix), - .i_vs (hvs_fix), - .i_fl (f1), - .i_de (hde_emu), - .iauto (1), - .himin (0), - .himax (0), - .vimin (0), - .vimax (0), - - .o_clk (clk_hdmi), - .o_ce (scaler_out), - .o_r (hdmi_data[23:16]), - .o_g (hdmi_data[15:8]), - .o_b (hdmi_data[7:0]), - .o_hs (hdmi_hs), - .o_vs (hdmi_vs), - .o_de (hdmi_de), - .o_vbl (hdmi_vbl), - .o_brd (hdmi_brd), - .o_lltune (lltune), - .htotal (WIDTH + HFP + HBP + HS[11:0]), - .hsstart (WIDTH + HFP), - .hsend (WIDTH + HFP + HS[11:0]), - .hdisp (WIDTH), - .hmin (hmin), - .hmax (hmax), - .vtotal (HEIGHT + VFP + VBP + VS[11:0]), - .vsstart (HEIGHT + VFP), - .vsend (HEIGHT + VFP + VS[11:0]), - .vdisp (HEIGHT), - .vmin (vmin), - .vmax (vmax), - .vrr (vrr_mode), - .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), - - .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), - .poly_clk (clk_sys), - .poly_a (coef_addr), - .poly_dw (coef_data), - .poly_wr (coef_wr), - - .pal1_clk (clk_pal), - .pal1_dw (pal_d), - .pal1_a (pal_a), - .pal1_wr (pal_wr), - -`ifdef MISTER_FB - `ifdef MISTER_FB_PALETTE - .pal2_clk (fb_pal_clk), - .pal2_dw (fb_pal_d), - .pal2_dr (fb_pal_q), - .pal2_a (fb_pal_a), - .pal2_wr (fb_pal_wr), - .pal_n (fb_en), + `ifdef MISTER_DISABLE_ADAPTIVE + .ADAPTIVE("false"), + `endif + `ifdef MISTER_DOWNSCALE_NN + .DOWNSCALE_NN("true"), + `endif + .FRAC(8), + .N_DW(128), + .N_AW(28) + ) + ascal + ( + .reset_na (~reset_req), + .run (1), + .freeze (freeze), + + .i_clk (clk_ihdmi), + .i_ce (ce_hpix), + .i_r (hr_out), + .i_g (hg_out), + .i_b (hb_out), + .i_hs (hhs_fix), + .i_vs (hvs_fix), + .i_fl (f1), + .i_de (hde_emu), + .iauto (1), + .himin (0), + .himax (0), + .vimin (0), + .vimax (0), + + .o_clk (clk_hdmi), + .o_ce (scaler_out), + .o_r (hdmi_data[23:16]), + .o_g (hdmi_data[15:8]), + .o_b (hdmi_data[7:0]), + .o_hs (hdmi_hs), + .o_vs (hdmi_vs), + .o_de (hdmi_de), + .o_vbl (hdmi_vbl), + .o_brd (hdmi_brd), + .o_lltune (lltune), + .htotal (WIDTH + HFP + HBP + HS[11:0]), + .hsstart (WIDTH + HFP), + .hsend (WIDTH + HFP + HS[11:0]), + .hdisp (WIDTH), + .hmin (hmin), + .hmax (hmax), + .vtotal (HEIGHT + VFP + VBP + VS[11:0]), + .vsstart (HEIGHT + VFP), + .vsend (HEIGHT + VFP + VS[11:0]), + .vdisp (HEIGHT), + .vmin (vmin), + .vmax (vmax), + .vrr (vrr_mode), + .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), + + .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), + .poly_clk (clk_sys), + .poly_a (coef_addr), + .poly_dw (coef_data), + .poly_wr (coef_wr), + + .pal1_clk (clk_pal), + .pal1_dw (pal_d), + .pal1_a (pal_a), + .pal1_wr (pal_wr), + + `ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + .pal2_clk (fb_pal_clk), + .pal2_dw (fb_pal_d), + .pal2_dr (fb_pal_q), + .pal2_a (fb_pal_a), + .pal2_wr (fb_pal_wr), + .pal_n (fb_en), + `endif `endif -`endif - .o_fb_ena (FB_EN), - .o_fb_hsize (FB_WIDTH), - .o_fb_vsize (FB_HEIGHT), - .o_fb_format (FB_FMT), - .o_fb_base (FB_BASE), - .o_fb_stride (FB_STRIDE), - - .avl_clk (clk_100m), - .avl_waitrequest (vbuf_waitrequest), - .avl_readdata (vbuf_readdata), - .avl_readdatavalid(vbuf_readdatavalid), - .avl_burstcount (vbuf_burstcount), - .avl_writedata (vbuf_writedata), - .avl_address (vbuf_address), - .avl_write (vbuf_write), - .avl_read (vbuf_read), - .avl_byteenable (vbuf_byteenable) -); + .o_fb_ena (FB_EN), + .o_fb_hsize (FB_WIDTH), + .o_fb_vsize (FB_HEIGHT), + .o_fb_format (FB_FMT), + .o_fb_base (FB_BASE), + .o_fb_stride (FB_STRIDE), + + .avl_clk (clk_100m), + .avl_waitrequest (vbuf_waitrequest), + .avl_readdata (vbuf_readdata), + .avl_readdatavalid(vbuf_readdatavalid), + .avl_burstcount (vbuf_burstcount), + .avl_writedata (vbuf_writedata), + .avl_address (vbuf_address), + .avl_write (vbuf_write), + .avl_read (vbuf_read), + .avl_byteenable (vbuf_byteenable) + ); `endif reg LFB_EN = 0; @@ -820,8 +833,8 @@ always @(posedge clk_sys) begin end `ifdef MISTER_FB -reg fb_vbl; -always @(posedge clk_vid) fb_vbl <= hdmi_vbl; + reg fb_vbl; + always @(posedge clk_vid) fb_vbl <= hdmi_vbl; `endif reg ar_md_start; @@ -947,24 +960,24 @@ always @(posedge clk_vid) begin end `ifndef MISTER_DEBUG_NOHDMI -wire [15:0] lltune; -pll_hdmi_adj pll_hdmi_adj -( - .clk(FPGA_CLK1_50), - .reset_na(~reset_req), - - .llena(lowlat), - .lltune({16{cfg_done}} & lltune), - .locked(led_locked), - .i_waitrequest(adj_waitrequest), - .i_write(adj_write), - .i_address(adj_address), - .i_writedata(adj_data), - .o_waitrequest(cfg_waitrequest), - .o_write(cfg_write), - .o_address(cfg_address), - .o_writedata(cfg_data) -); + wire [15:0] lltune; + pll_hdmi_adj pll_hdmi_adj + ( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), + + .llena(lowlat), + .lltune({16{cfg_done}} & lltune), + .locked(led_locked), + .i_waitrequest(adj_waitrequest), + .i_write(adj_write), + .i_address(adj_address), + .i_writedata(adj_data), + .o_waitrequest(cfg_waitrequest), + .o_write(cfg_write), + .o_address(cfg_address), + .o_writedata(cfg_data) + ); `else assign led_locked = 0; `endif @@ -990,15 +1003,15 @@ end ///////////////////////// HDMI output ///////////////////////////////// `ifndef MISTER_DEBUG_NOHDMI -wire hdmi_clk_out; -pll_hdmi pll_hdmi -( - .refclk(FPGA_CLK1_50), - .rst(reset_req), - .reconfig_to_pll(reconfig_to_pll), - .reconfig_from_pll(reconfig_from_pll), - .outclk_0(hdmi_clk_out) -); + wire hdmi_clk_out; + pll_hdmi pll_hdmi + ( + .refclk(FPGA_CLK1_50), + .rst(reset_req), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + .outclk_0(hdmi_clk_out) + ); `endif //1920x1080@60 PCLK=148.5MHz CEA @@ -1023,64 +1036,59 @@ reg [5:0] adj_address; reg [31:0] adj_data; `ifndef MISTER_DEBUG_NOHDMI -pll_cfg pll_cfg -( - .mgmt_clk(FPGA_CLK1_50), - .mgmt_reset(reset_req), - .mgmt_waitrequest(cfg_waitrequest), - .mgmt_read(0), - .mgmt_readdata(), - .mgmt_write(cfg_write), - .mgmt_address(cfg_address), - .mgmt_writedata(cfg_data), - .reconfig_to_pll(reconfig_to_pll), - .reconfig_from_pll(reconfig_from_pll) -); + pll_cfg_hdmi pll_cfg_hdmi + ( + .mgmt_clk(FPGA_CLK1_50), + .mgmt_reset(reset_req), + .mgmt_waitrequest(cfg_waitrequest), + .mgmt_write(cfg_write), + .mgmt_address(cfg_address), + .mgmt_writedata(cfg_data), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); -reg cfg_got = 0; -always @(posedge clk_sys) begin - reg vsd, vsd2; - if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; - else begin - vsd <= HDMI_TX_VS; - vsd2 <= vsd; - if(~vsd2 & vsd) cfg_got <= cfg_set; + reg cfg_got = 0; + always @(posedge clk_sys) begin + reg vsd, vsd2; + if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; + else begin + vsd <= HDMI_TX_VS; + vsd2 <= vsd; + if(~vsd2 & vsd) cfg_got <= cfg_set; + end end -end -reg cfg_ready = 0; -always @(posedge FPGA_CLK1_50) begin - reg gotd = 0, gotd2 = 0; - reg custd = 0, custd2 = 0; - reg old_wait = 0; + reg cfg_ready = 0; + always @(posedge FPGA_CLK1_50) begin + reg gotd = 0, gotd2 = 0; + reg custd = 0, custd2 = 0; + reg old_wait = 0; + + gotd <= cfg_got; + gotd2 <= gotd; + + adj_write <= 0; + + custd <= cfg_custom_t; + custd2 <= custd; + if(custd2 != custd & ~gotd) begin + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; + end - gotd <= cfg_got; - gotd2 <= gotd; - - adj_write <= 0; - - custd <= cfg_custom_t; - custd2 <= custd; - if(custd2 != custd & ~gotd) begin - adj_address <= cfg_custom_p1; - adj_data <= cfg_custom_p2; - adj_write <= 1; - end + if(~gotd2 & gotd) begin + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; + end - if(~gotd2 & gotd) begin - adj_address <= 2; - adj_data <= 0; - adj_write <= 1; + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; end - - old_wait <= adj_waitrequest; - if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; -end - `else - -wire cfg_ready = 1; - + wire cfg_ready = 1; `endif assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ; @@ -1096,72 +1104,71 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c ); `ifndef MISTER_DEBUG_NOHDMI + `ifdef MISTER_FB + reg dis_output; + always @(posedge clk_hdmi) begin + reg dis; + dis <= fb_force_blank & ~LFB_EN; + dis_output <= dis; + end + `else + wire dis_output = 0; + `endif -`ifdef MISTER_FB -reg dis_output; -always @(posedge clk_hdmi) begin - reg dis; - dis <= fb_force_blank & ~LFB_EN; - dis_output <= dis; -end -`else -wire dis_output = 0; -`endif - -wire [23:0] hdmi_data_mask; -wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; - -reg [15:0] shadowmask_data; -reg shadowmask_wr = 0; - -shadowmask HDMI_shadowmask -( - .clk(clk_hdmi), - .clk_sys(clk_sys), - - .cmd_wr(shadowmask_wr), - .cmd_in(shadowmask_data), - - .din(dis_output ? 24'd0 : hdmi_data), - .hs_in(hdmi_hs), - .vs_in(hdmi_vs), - .de_in(hdmi_de), - .brd_in(hdmi_brd), - .enable(~LFB_EN), - - .dout(hdmi_data_mask), - .hs_out(hdmi_hs_mask), - .vs_out(hdmi_vs_mask), - .de_out(hdmi_de_mask) -); + wire [23:0] hdmi_data_mask; + wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; -wire [23:0] hdmi_data_osd; -wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; + reg [15:0] shadowmask_data; + reg shadowmask_wr = 0; -osd hdmi_osd -( - .clk_sys(clk_sys), + shadowmask HDMI_shadowmask + ( + .clk(clk_hdmi), + .clk_sys(clk_sys), + + .cmd_wr(shadowmask_wr), + .cmd_in(shadowmask_data), + + .din(dis_output ? 24'd0 : hdmi_data), + .hs_in(hdmi_hs), + .vs_in(hdmi_vs), + .de_in(hdmi_de), + .brd_in(hdmi_brd), + .enable(~LFB_EN), + + .dout(hdmi_data_mask), + .hs_out(hdmi_hs_mask), + .vs_out(hdmi_vs_mask), + .de_out(hdmi_de_mask) + ); - .io_osd(io_osd_hdmi), - .io_strobe(io_strobe), - .io_din(io_din), + wire [23:0] hdmi_data_osd; + wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; - .clk_video(clk_hdmi), - .din(hdmi_data_mask), - .hs_in(hdmi_hs_mask), - .vs_in(hdmi_vs_mask), - .de_in(hdmi_de_mask), + osd hdmi_osd + ( + .clk_sys(clk_sys), + + .io_osd(io_osd_hdmi), + .io_strobe(io_strobe), + .io_din(io_din), + + .clk_video(clk_hdmi), + .din(hdmi_data_mask), + .hs_in(hdmi_hs_mask), + .vs_in(hdmi_vs_mask), + .de_in(hdmi_de_mask), + + .dout(hdmi_data_osd), + .hs_out(hdmi_hs_osd), + .vs_out(hdmi_vs_osd), + .de_out(hdmi_de_osd) + ); - .dout(hdmi_data_osd), - .hs_out(hdmi_hs_osd), - .vs_out(hdmi_vs_osd), - .de_out(hdmi_de_osd) -); + wire hdmi_cs_osd; + csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); `endif -wire hdmi_cs_osd; -csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); - reg [23:0] dv_data; reg dv_hs, dv_vs, dv_de; wire [23:0] dv_data_osd; @@ -1194,11 +1201,12 @@ always @(posedge clk_vid) begin end dv_de1 <= !{hss,dv_hs_osd} && vde; - dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; - dv_vs1 <= dv_vs_osd; end dv_d1 <= dv_data_osd; + dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; + dv_vs1 <= dv_vs_osd; + dv_d2 <= dv_d1; dv_de2 <= dv_de1; dv_hs2 <= dv_hs1; @@ -1211,21 +1219,21 @@ always @(posedge clk_vid) begin end `ifndef MISTER_DISABLE_YC -assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; `else -assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; `endif wire hdmi_tx_clk; `ifndef MISTER_DEBUG_NOHDMI -cyclonev_clkselect hdmi_clk_sw -( - .clkselect({1'b1, ~vga_fb & direct_video}), - .inclk({clk_vid, hdmi_clk_out, 2'b00}), - .outclk(hdmi_tx_clk) -); + cyclonev_clkselect hdmi_clk_sw + ( + .clkselect({1'b1, ~vga_fb & direct_video}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(hdmi_tx_clk) + ); `else -assign hdmi_tx_clk = clk_vid; + assign hdmi_tx_clk = clk_vid; `endif altddio_out @@ -1270,10 +1278,17 @@ always @(posedge hdmi_tx_clk) begin hdmi_dv_vs <= dv_vs; hdmi_dv_de <= dv_de; +`ifndef MISTER_DEBUG_NOHDMI hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd; vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd; de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd; d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd; +`else + hs <= hdmi_dv_hs; + vs <= hdmi_dv_vs; + de <= hdmi_dv_de; + d <= hdmi_dv_data; +`endif hdmi_out_hs <= hs; hdmi_out_vs <= vs; @@ -1288,6 +1303,46 @@ assign HDMI_TX_D = hdmi_out_d; ///////////////////////// VGA output ////////////////////////////////// +`ifndef MISTER_DUAL_SDRAM + wire vga_tx_clk; + `ifndef MISTER_DEBUG_NOHDMI + cyclonev_clkselect vga_clk_sw + ( + .clkselect({1'b1, ~vga_fb & ~vga_scaler}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(vga_tx_clk) + ); + `else + assign vga_tx_clk = clk_vid; + `endif + + wire VGA_TX_CLK; + altddio_out + #( + .extend_oe_disable("OFF"), + .intended_device_family("Cyclone V"), + .invert_output("OFF"), + .lpm_hint("UNUSED"), + .lpm_type("altddio_out"), + .oe_reg("UNREGISTERED"), + .power_up_high("OFF"), + .width(1) + ) + vgaclk_ddr + ( + .datain_h(1'b0), + .datain_l(1'b1), + .outclock(vga_tx_clk), + .dataout(VGA_TX_CLK), + .aclr(~mcp_en & ~av_dis), + .aset(1'b0), + .oe(~av_dis & (mcp_en | ~led_u)), + .outclocken(1'b1), + .sclr(1'b0), + .sset(1'b0) + ); +`endif + wire [23:0] vga_data_sl; wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl; scanlines #(0) VGA_scanlines @@ -1309,7 +1364,7 @@ scanlines #(0) VGA_scanlines ); wire [23:0] vga_data_osd; -wire vga_vs_osd, vga_hs_osd; +wire vga_vs_osd, vga_hs_osd, vga_de_osd; osd vga_osd ( .clk_sys(clk_sys), @@ -1327,46 +1382,13 @@ osd vga_osd .dout(vga_data_osd), .hs_out(vga_hs_osd), - .vs_out(vga_vs_osd) + .vs_out(vga_vs_osd), + .de_out(vga_de_osd) ); wire vga_cs_osd; csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); -`ifndef MISTER_DUAL_SDRAM - wire VGA_DISABLE; - wire [23:0] vgas_o; - wire vgas_hs, vgas_vs, vgas_cs; - vga_out vga_scaler_out - ( - .clk(clk_hdmi), - .ypbpr_en(ypbpr_en), - .hsync(hdmi_hs_osd), - .vsync(hdmi_vs_osd), - .csync(hdmi_cs_osd), - .dout(vgas_o), - .din({24{hdmi_de_osd}} & hdmi_data_osd), - .hsync_o(vgas_hs), - .vsync_o(vgas_vs), - .csync_o(vgas_cs) - ); - - wire [23:0] vga_o, vga_o_t; - wire vga_hs, vga_vs, vga_cs, vga_hs_t, vga_vs_t, vga_cs_t; - vga_out vga_out - ( - .clk(clk_vid), - .ypbpr_en(ypbpr_en), - .hsync(vga_hs_osd), - .vsync(vga_vs_osd), - .csync(vga_cs_osd), - .dout(vga_o_t), - .din(vga_data_osd), - .hsync_o(vga_hs_t), - .vsync_o(vga_vs_t), - .csync_o(vga_cs_t) - ); - `ifndef MISTER_DISABLE_YC reg pal_en; reg yc_en; @@ -1374,7 +1396,7 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); reg [16:0] ColorBurst_Range; reg [39:0] PhaseInc; wire [23:0] yc_o; - wire yc_hs, yc_vs, yc_cs; + wire yc_hs, yc_vs, yc_cs, yc_de; yc_out yc_out ( @@ -1386,25 +1408,78 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); .hsync(vga_hs_osd), .vsync(vga_vs_osd), .csync(vga_cs_osd), + .de(vga_de_osd), .dout(yc_o), .din(vga_data_osd), .hsync_o(yc_hs), .vsync_o(yc_vs), - .csync_o(yc_cs) + .csync_o(yc_cs), + .de_o(yc_de) ); - - assign {vga_o, vga_hs, vga_vs, vga_cs } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } : {yc_o, yc_hs, yc_vs, yc_cs }; -`else - assign {vga_o, vga_hs, vga_vs, vga_cs } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t } ; `endif - wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs; +`ifndef MISTER_DUAL_SDRAM + wire VGA_DISABLE; + wire [23:0] vgas_o; + wire vgas_hs, vgas_vs, vgas_cs, vgas_de; + `ifndef MISTER_DEBUG_NOHDMI + vga_out vga_scaler_out + ( + .clk(clk_hdmi), + .ypbpr_en(ypbpr_en), + .hsync(hdmi_hs_osd), + .vsync(hdmi_vs_osd), + .csync(hdmi_cs_osd), + .de(hdmi_de_osd), + .dout(vgas_o), + .din({24{hdmi_de_osd}} & hdmi_data_osd), + .hsync_o(vgas_hs), + .vsync_o(vgas_vs), + .csync_o(vgas_cs), + .de_o(vgas_de) + ); + `else + assign {vgas_o, vgas_hs, vgas_vs, vgas_cs, vgas_de} = 0; + `endif + + wire [23:0] vga_o, vga_o_t; + wire vga_hs, vga_vs, vga_cs, vga_de, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t; + vga_out vga_out + ( + .clk(clk_vid), + .ypbpr_en(ypbpr_en), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .de(vga_de_osd), + .dout(vga_o_t), + .din(vga_data_osd), + .hsync_o(vga_hs_t), + .vsync_o(vga_vs_t), + .csync_o(vga_cs_t), + .de_o(vga_de_t) + ); + + `ifndef MISTER_DISABLE_YC + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } : {yc_o, yc_hs, yc_vs, yc_cs, yc_de }; + `else + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } ; + `endif + + wire vgas_en = vga_fb | vga_scaler; - assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); - assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); - assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; - assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; - assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; + wire cs1 = vgas_en ? vgas_cs : vga_cs; + wire de1 = vgas_en ? vgas_de : vga_de; + + assign VGA_VS = av_dis ? 1'bZ : ((vgas_en ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); + assign VGA_HS = av_dis ? 1'bZ : (vgas_en ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); + assign VGA_R = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; + assign VGA_G = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; + assign VGA_B = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; + + wire [1:0] vga_r = vgas_en ? vgas_o[17:16] : VGA_DISABLE ? 2'd0 : vga_o[17:16]; + wire [1:0] vga_g = vgas_en ? vgas_o[9:8] : VGA_DISABLE ? 2'd0 : vga_o[9:8]; + wire [1:0] vga_b = vgas_en ? vgas_o[1:0] : VGA_DISABLE ? 2'd0 : vga_o[1:0]; `endif reg video_sync = 0; @@ -1434,14 +1509,14 @@ end ///////////////////////// Audio output //////////////////////////////// -assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ; +assign SDCD_SPDIF = (mcp_en & ~spdif) ? 1'b0 : 1'bZ; `ifndef MISTER_DUAL_SDRAM wire analog_l, analog_r; - assign AUDIO_SPDIF = SW[3] ? 1'bZ : SW[0] ? HDMI_LRCLK : spdif; - assign AUDIO_R = SW[3] ? 1'bZ : SW[0] ? HDMI_I2S : analog_r; - assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : analog_l; + assign AUDIO_SPDIF = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_LRCLK : spdif; + assign AUDIO_R = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_I2S : analog_r; + assign AUDIO_L = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_SCLK : analog_l; `endif assign HDMI_MCLK = clk_audio; @@ -1477,8 +1552,10 @@ audio_out audio_out .core_l(audio_l), .core_r(audio_r), +`ifndef MISTER_DISABLE_ALSA .alsa_l(alsa_l), .alsa_r(alsa_r), +`endif .i2s_bclk(HDMI_SCLK), .i2s_lrclk(HDMI_LRCLK), @@ -1491,32 +1568,45 @@ audio_out audio_out ); -wire [28:0] alsa_address; -wire [63:0] alsa_readdata; -wire alsa_ready; -wire alsa_req; -wire alsa_late; +`ifndef MISTER_DISABLE_ALSA + wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; + cyclonev_hps_interface_peripheral_spi_master spi + ( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(aspi_miso), // miso -wire [15:0] alsa_l, alsa_r; + .ss_0_n(aspi_ss), + .ss_in_n(1) + ); -alsa alsa -( - .reset(reset), - .clk(clk_audio), + wire [28:0] alsa_address; + wire [63:0] alsa_readdata; + wire alsa_ready; + wire alsa_req; + wire alsa_late; + + wire [15:0] alsa_l, alsa_r; - .ram_address(alsa_address), - .ram_data(alsa_readdata), - .ram_req(alsa_req), - .ram_ready(alsa_ready), + alsa alsa + ( + .reset(reset), + .clk(clk_audio), - .spi_ss(aspi_ss), - .spi_sck(aspi_sck), - .spi_mosi(aspi_mosi), - .spi_miso(aspi_miso), + .ram_address(alsa_address), + .ram_data(alsa_readdata), + .ram_req(alsa_req), + .ram_ready(alsa_ready), - .pcm_l(alsa_l), - .pcm_r(alsa_r) -); + .spi_ss(aspi_ss), + .spi_sck(aspi_sck), + .spi_mosi(aspi_mosi), + .spi_miso(aspi_miso), + + .pcm_l(alsa_l), + .pcm_r(alsa_r) + ); +`endif //////////////// User I/O (USB 3.0 connector) ///////////////////////// @@ -1716,7 +1806,7 @@ emu emu .SDRAM2_nRAS(SDRAM2_nRAS), .SDRAM2_nCAS(SDRAM2_nCAS), .SDRAM2_CLK(SDRAM2_CLK), - .SDRAM2_EN(SW[3]), + .SDRAM2_EN(io_dig), `endif .BUTTONS(btn), @@ -1726,11 +1816,7 @@ emu emu .SD_MOSI(SD_MOSI), .SD_MISO(SD_MISO), .SD_CS(SD_CS), -`ifdef MISTER_DUAL_SDRAM - .SD_CD(mcp_sdcd), -`else - .SD_CD(mcp_sdcd & (SW[0] ? VGA_HS : (SW[3] | SDCD_SPDIF))), -`endif + .SD_CD(SD_CD), .UART_CTS(uart_rts), .UART_RTS(uart_cts), @@ -1759,19 +1845,17 @@ assign sync_out = sync_in ^ pol; reg pol; always @(posedge clk) begin - integer pos = 0, neg = 0, cnt = 0; + reg [31:0] cnt; reg s1,s2; s1 <= sync_in; s2 <= s1; + cnt <= s2 ? (cnt - 1) : (cnt + 1); - if(~s2 & s1) neg <= cnt; - if(s2 & ~s1) pos <= cnt; - - cnt <= cnt + 1; - if(s2 != s1) cnt <= 0; - - pol <= pos > neg; + if(~s2 & s1) begin + cnt <= 0; + pol <= cnt[31]; + end end endmodule diff --git a/sys/vga_out.sv b/sys/vga_out.sv index fe8172b..4160635 100644 --- a/sys/vga_out.sv +++ b/sys/vga_out.sv @@ -7,23 +7,27 @@ module vga_out input hsync, input vsync, input csync, + input de, input [23:0] din, output [23:0] dout, output reg hsync_o, output reg vsync_o, - output reg csync_o + output reg csync_o, + output reg de_o ); -wire [5:0] red = din[23:18]; -wire [5:0] green = din[15:10]; -wire [5:0] blue = din[7:2]; +wire [7:0] red = din[23:16]; +wire [7:0] green = din[15:8]; +wire [7:0] blue = din[7:0]; // http://marsee101.blog19.fc2.com/blog-entry-2311.html -// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) -// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) -// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + + +// Y = 0.301*R + 0.586*G + 0.113*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.168*R - 0.332*G + 0.500*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.500*R - 0.418*G - 0.082*B (Pr = 0.500*R - 0.419*G - 0.081*B) reg [7:0] y, pb, pr; reg [23:0] rgb; @@ -33,32 +37,33 @@ always @(posedge clk) begin reg [18:0] y_1b, pb_1b, pr_1b; reg [18:0] y_2, pb_2, pr_2; reg [23:0] din1, din2; - reg hsync2, vsync2, csync2; - reg hsync1, vsync1, csync1; + reg hsync2, vsync2, csync2, de2; + reg hsync1, vsync1, csync1, de1; - y_1r <= 19'd04096 + ({red, 8'd0} + {red, 3'd0}); - pb_1r <= 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}); - pr_1r <= 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}); + y_1r <= {red, 6'd0} + {red, 3'd0} + {red, 2'd0} + red; + pb_1r <= 19'd32768 - ({red, 5'd0} + {red, 3'd0} + {red, 1'd0}); + pr_1r <= 19'd32768 + {red, 7'd0}; - y_1g <= {green, 9'd0} + {green, 2'd0}; - pb_1g <= {green, 8'd0} + {green, 5'd0} + {green, 3'd0}; - pr_1g <= {green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}; + y_1g <= {green, 7'd0} + {green, 4'd0} + {green, 2'd0} + {green, 1'd0}; + pb_1g <= {green, 6'd0} + {green, 4'd0} + {green, 2'd0} + green; + pr_1g <= {green, 6'd0} + {green, 5'd0} + {green, 3'd0} + {green, 1'd0}; - y_1b <= {blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}; - pb_1b <= {blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}; - pr_1b <= {blue, 6'd0} + {blue, 3'd0}; + y_1b <= {blue, 4'd0} + {blue, 3'd0} + {blue, 2'd0} + blue; + pb_1b <= {blue, 7'd0}; + pr_1b <= {blue, 4'd0} + {blue, 2'd0} + blue; y_2 <= y_1r + y_1g + y_1b; pb_2 <= pb_1r - pb_1g + pb_1b; pr_2 <= pr_1r - pr_1g - pr_1b; - y <= ( y_2[18] || !y_2[17:12]) ? 8'd16 : (y_2[17:8] > 235) ? 8'd235 : y_2[15:8]; - pb <= (pb_2[18] || !pb_2[17:12]) ? 8'd16 : (&pb_2[17:12]) ? 8'd240 : pb_2[15:8]; - pr <= (pr_2[18] || !pr_2[17:12]) ? 8'd16 : (&pr_2[17:12]) ? 8'd240 : pr_2[15:8]; + y <= y_2[18] ? 8'd0 : y_2[16] ? 8'd255 : y_2[15:8]; + pb <= pb_2[18] ? 8'd0 : pb_2[16] ? 8'd255 : pb_2[15:8]; + pr <= pr_2[18] ? 8'd0 : pr_2[16] ? 8'd255 : pr_2[15:8]; hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync; vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync; csync_o <= csync2; csync2 <= csync1; csync1 <= csync; + de_o <= de2; de2 <= de1; de1 <= de; rgb <= din2; din2 <= din1; din1 <= din; end diff --git a/sys/video_freak.sv b/sys/video_freak.sv index 18beb03..65375cd 100644 --- a/sys/video_freak.sv +++ b/sys/video_freak.sv @@ -170,10 +170,8 @@ reg [11:0] mul_arg1, mul_arg2; wire [23:0] mul_res; sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); -wire [11:0] wideres = mul_res[11:0] + hsize; - always @(posedge CLK_VIDEO) begin - reg [11:0] oheight,wres; + reg [11:0] oheight,htarget,wres,hinteger,wideres; reg [12:0] arxf,aryf; reg [3:0] cnt; reg narrow; @@ -188,11 +186,18 @@ always @(posedge CLK_VIDEO) begin else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin cnt <= cnt + 1'd1; case(cnt) + // example ideal and non-ideal cases: + // [1] 720x400 4:3 VGA 80x25 text-mode (non-square pixels) + // [2] 640x480 4:3 VGA graphics mode (square pixels) + // [3] 512x512 4:3 X68000 graphics mode (non-square pixels) 0: begin div_num <= HDMI_HEIGHT; div_den <= vsize; div_start <= 1; end + // [1] 1080 / 400 -> 2 + // [2] 1080 / 480 -> 2 + // [3] 1080 / 512 -> 2 1: if(!div_res[11:0]) begin // screen resolution is lower than video resolution. @@ -206,6 +211,9 @@ always @(posedge CLK_VIDEO) begin mul_arg2 <= div_res[11:0]; mul_start <= 1; end + // [1] 1080 / 400 * 400 -> 800 + // [2] 1080 / 480 * 480 -> 960 + // [3] 1080 / 512 * 512 -> 1024 2: begin oheight <= mul_res[11:0]; @@ -219,27 +227,43 @@ always @(posedge CLK_VIDEO) begin mul_arg2 <= arx_i; mul_start <= 1; end + // [1] 1080 / 400 * 400 * 4 -> 3200 + // [2] 1080 / 480 * 480 * 4 -> 3840 + // [3] 1080 / 512 * 512 * 4 -> 4096 4: begin div_num <= mul_res; div_den <= ary_i; div_start <= 1; end + // [1] 1080 / 480 * 480 * 4 / 3 -> 1066 + // [2] 1080 / 480 * 480 * 4 / 3 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 -> 1365 + // saved as htarget 5: begin + htarget <= div_res[11:0]; div_num <= div_res; div_den <= hsize; div_start <= 1; end + // computes wide scaling factor as a ceiling division + // [1] 1080 / 400 * 400 * 4 / 3 / 720 -> 1 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 -> 2 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 -> 2 6: begin mul_arg1 <= hsize; mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; mul_start <= 1; end + // [1] 1080 / 400 * 400 * 4 / 3 / 720 * 720 -> 720 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 * 640 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 * 512 -> 1024 7: if(mul_res <= HDMI_WIDTH) begin - cnt <= 10; + hinteger = mul_res[11:0]; + cnt <= 12; end 8: begin @@ -247,23 +271,50 @@ always @(posedge CLK_VIDEO) begin div_den <= hsize; div_start <= 1; end + // [1] 1920 / 720 -> 2 + // [2] 1920 / 640 -> 3 + // [3] 1920 / 512 -> 3 9: begin mul_arg1 <= hsize; mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; mul_start <= 1; end - - 10: begin - narrow <= ((div_num[11:0] - mul_res[11:0]) <= (wideres - div_num[11:0])) || (wideres > HDMI_WIDTH); - wres <= wideres; + // [1] 1920 / 720 * 720 -> 1440 + // [2] 1920 / 640 * 640 -> 1920 + // [3] 1920 / 512 * 512 -> 1536 + + 10: begin + hinteger <= mul_res[11:0]; + mul_arg1 <= vsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + + 11: begin + oheight <= mul_res[11:0]; + end + + 12: begin + wideres <= hinteger + hsize; + narrow <= ((htarget - hinteger) <= (wideres - htarget)) || (wideres > HDMI_WIDTH); + wres <= hinteger == htarget ? hinteger : wideres; end - - 11: begin + // [1] 1066 - 720 = 346 <= 1440 - 1066 = 374 || 1440 > 1920 -> true + // [2] 1280 - 1280 = 0 <= 1920 - 1280 = 640 || 1920 > 1920 -> true + // [3] 1365 - 1024 = 341 <= 1536 - 1365 = 171 || 1536 > 1920 -> false + // 1. narrow flag is true when mul_res[11:0] narrow width is closer to + // htarget aspect ratio target width or when wideres wider width + // does not fit to the screen. + // 2. wres becomes wideres only when mul_res[11:0] narrow width not equal + // to target width, meaning it is not optimal for source aspect ratio. + // otherwise it is set to narrow width that is optimal. + + 13: begin case(SCALE) - 2: arxf <= {1'b1, mul_res[11:0]}; - 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? mul_res[11:0] : wres}; - 4: arxf <= {1'b1, narrow ? mul_res[11:0] : wres}; + 2: arxf <= {1'b1, hinteger}; + 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? hinteger : wres}; + 4: arxf <= {1'b1, narrow ? hinteger : wres}; default: arxf <= {1'b1, div_num[11:0]}; endcase aryf <= {1'b1, oheight}; diff --git a/sys/yc_out.sv b/sys/yc_out.sv index 2e9a24e..984fc37 100644 --- a/sys/yc_out.sv +++ b/sys/yc_out.sv @@ -36,13 +36,15 @@ module yc_out input hsync, input vsync, input csync, + input de, input [23:0] din, output [23:0] dout, output reg hsync_o, output reg vsync_o, - output reg csync_o + output reg csync_o, + output reg de_o ); wire [7:0] red = din[23:16]; @@ -61,6 +63,7 @@ typedef struct { logic hsync; logic vsync; logic csync; + logic de; } phase_t; localparam MAX_PHASES = 7'd8; @@ -211,11 +214,11 @@ always_ff @(posedge clk) begin end // Adjust sync timing correctly - phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; - phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; - phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; - phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; - hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; + phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; phase[1].de <= de; + phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; phase[2].de <= phase[1].de; + phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; phase[3].de <= phase[2].de; + phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; phase[4].de <= phase[3].de; + hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; de_o <= phase[4].de; phase[1].y <= phase[0].y; phase[2].y <= phase[1].y; phase[3].y <= phase[2].y; phase[4].y <= phase[3].y; phase[5].y <= phase[4].y;