From cc1962452b181de9c48fdcdb7ffbcc93c224802e Mon Sep 17 00:00:00 2001 From: sorgelig Date: Thu, 28 Jan 2021 00:07:29 +0800 Subject: [PATCH] Update sys. --- menu.sv | 64 ++++++- sys/arcade_video.v | 8 +- sys/ascal.vhd | 9 +- sys/f2sdram_safe_terminator.sv | 300 +++++++++++++++++++++++++++++++++ sys/hdmi_config.sv | 44 ++--- sys/hps_io.v | 17 +- sys/mt32pi.sv | 283 +++++++++++++++++++++++++++++++ sys/sd_card.sv | 9 +- sys/spdif.v | 19 ++- sys/sys.qip | 2 + sys/sys_top.sdc | 36 ++-- sys/sys_top.v | 101 ++++++++--- sys/sysmem.sv | 195 ++++++++++++++++++--- sys/vga_out.sv | 74 ++++---- 14 files changed, 1010 insertions(+), 151 deletions(-) create mode 100644 sys/f2sdram_safe_terminator.sv create mode 100644 sys/mt32pi.sv diff --git a/menu.sv b/menu.sv index b14c187..af00c99 100644 --- a/menu.sv +++ b/menu.sv @@ -39,8 +39,8 @@ module emu output CE_PIXEL, //Video aspect ratio for HDMI. Most retro systems have ratio 4:3. - output [7:0] VIDEO_ARX, - output [7:0] VIDEO_ARY, + output [11:0] VIDEO_ARX, + output [11:0] VIDEO_ARY, output [7:0] VGA_R, output [7:0] VGA_G, @@ -50,6 +50,34 @@ module emu output VGA_DE, // = ~(VBlank | HBlank) output VGA_F1, output [1:0] VGA_SL, + output VGA_SCALER, // Force VGA scaler + +`ifdef USE_FB + // Use framebuffer in DDRAM (USE_FB=1 in qsf) + // FB_FORMAT: + // [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + // [3] : 0=16bits 565 1=16bits 1555 + // [4] : 0=RGB 1=BGR (for 16/24/32 modes) + // + // FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes) + output FB_EN, + output [4:0] FB_FORMAT, + output [11:0] FB_WIDTH, + output [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + output [13:0] FB_STRIDE, + input FB_VBL, + input FB_LL, + output FB_FORCE_BLANK, + + // Palette control for 8bit modes. + // Ignored for other video modes. + output FB_PAL_CLK, + output [7:0] FB_PAL_ADDR, + output [23:0] FB_PAL_DOUT, + input [23:0] FB_PAL_DIN, + output FB_PAL_WR, +`endif output LED_USER, // 1 - ON, 0 - OFF. @@ -58,13 +86,13 @@ module emu // hint: supply 2'b00 to let the system control the LED. output [1:0] LED_POWER, output [1:0] LED_DISK, - - // I/O board button press simulation (active high) - // b[1]: user button - // b[0]: osd button - output [1:0] BUTTONS, - - input CLK_AUDIO, // 24.576 MHz + + // I/O board button press simulation (active high) + // b[1]: user button + // b[0]: osd button + output [1:0] BUTTONS, + + input CLK_AUDIO, // 24.576 MHz output [15:0] AUDIO_L, output [15:0] AUDIO_R, output AUDIO_S, // 1 - signed audio samples, 0 - unsigned @@ -80,6 +108,7 @@ module emu output SD_CS, input SD_CD, +`ifdef USE_DDRAM //High latency DDR3 RAM interface //Use for non-critical time purposes output DDRAM_CLK, @@ -92,7 +121,9 @@ module emu output [63:0] DDRAM_DIN, output [7:0] DDRAM_BE, output DDRAM_WE, +`endif +`ifdef USE_SDRAM //SDRAM interface with lower latency output SDRAM_CLK, output SDRAM_CKE, @@ -105,6 +136,20 @@ module emu output SDRAM_nCAS, output SDRAM_nRAS, output SDRAM_nWE, +`endif + +`ifdef DUAL_SDRAM + //Secondary SDRAM + input SDRAM2_EN, + output SDRAM2_CLK, + output [12:0] SDRAM2_A, + output [1:0] SDRAM2_BA, + inout [15:0] SDRAM2_DQ, + output SDRAM2_nCS, + output SDRAM2_nCAS, + output SDRAM2_nRAS, + output SDRAM2_nWE, +`endif input UART_CTS, output UART_RTS, @@ -136,6 +181,7 @@ assign VGA_SL = 0; assign VGA_F1 = 0; assign VIDEO_ARX = 0; assign VIDEO_ARY = 0; +assign VGA_SCALER= 0; assign AUDIO_S = 0; assign AUDIO_L = 0; diff --git a/sys/arcade_video.v b/sys/arcade_video.v index dd6dfc6..a1683f5 100644 --- a/sys/arcade_video.v +++ b/sys/arcade_video.v @@ -204,7 +204,7 @@ assign DDRAM_DIN = {ram_data,ram_data}; assign DDRAM_WE = ram_wr; assign DDRAM_RD = 0; -assign FB_EN = ~no_rotate; +assign FB_EN = fb_en[2]; assign FB_FORMAT = 5'b00110; assign FB_BASE = {MEM_BASE,o_fb,23'd0}; assign FB_WIDTH = vsz; @@ -236,6 +236,11 @@ always @(posedge CLK_VIDEO) begin end end +initial begin + fb_en = 0; +end + +reg [2:0] fb_en = 0; reg [11:0] hsz = 320, vsz = 240; reg [11:0] bwidth; reg [22:0] bufsize; @@ -257,6 +262,7 @@ always @(posedge CLK_VIDEO) begin vsz <= vcnt; bwidth <= vcnt + 2'd3; vcnt <= 0; + fb_en <= {fb_en[1:0], ~no_rotate}; end if(old_vs & ~VGA_VS) bufsize <= hsz * stride; end diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 30d6287..6d687ac 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -462,8 +462,8 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_fload : natural RANGE 0 TO 3; SIGNAL o_acpt,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO SIGNAL o_dshi : natural RANGE 0 TO 3; - SIGNAL o_first,o_last,o_last1,o_last2,o_last3 : std_logic; - SIGNAL o_lastt1,o_lastt2,o_lastt3 : std_logic; + SIGNAL o_first,o_last,o_last1,o_last2 : std_logic; + SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic; SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0); SIGNAL o_hdown,o_vdown : std_logic; SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); @@ -2029,7 +2029,8 @@ BEGIN o_acpt1<=o_acpt; o_acpt2<=o_acpt1; o_acpt3<=o_acpt2; o_acpt4<=o_acpt3; o_ad1<=o_ad; o_ad2<=o_ad1; o_ad3<=o_ad2; o_sh1<=o_sh; o_sh2<=o_sh1; o_sh3<=o_sh2; o_sh4<=o_sh3; - o_lastt1<=o_last; o_lastt2<=o_lastt1; o_lastt3<=o_lastt2; + o_lastt1<=o_last; o_lastt2<=o_lastt1; + o_lastt3<=o_lastt2; o_lastt4<=o_lastt3; ------------------------------------------------------ IF o_sh3='1' THEN @@ -2059,7 +2060,7 @@ BEGIN o_hpix2<=hpix_v; o_first<='0'; END IF; - IF o_lastt3='1' THEN + IF o_lastt4='1' THEN -- Right edge. Keep last pixel. o_hpix0<=o_hpix0; END IF; diff --git a/sys/f2sdram_safe_terminator.sv b/sys/f2sdram_safe_terminator.sv new file mode 100644 index 0000000..fb4c550 --- /dev/null +++ b/sys/f2sdram_safe_terminator.sv @@ -0,0 +1,300 @@ +// ============================================================================ +// +// f2sdram_safe_terminator for MiSTer platform +// +// ============================================================================ +// Copyright (c) 2021 bellwood420 +// +// Background: +// +// Terminating a transaction of burst writing(/reading) in its midstream +// seems to cause an illegal state to f2sdram interface. +// +// Forced reset request that occurs when loading other core is inevitable. +// +// So if it happens exactly within the transaction period, +// unexpected issues with accessing to f2sdram interface will be caused +// in next loaded core. +// +// It seems that only way to reset broken f2sdram interface is to reset +// whole SDRAM Controller Subsystem from HPS via permodrst register +// in Reset Manager. +// But it cannot be done safely while Linux is running. +// It is usually done when cold or warm reset is issued in HPS. +// +// Main_MiSTer is issuing reset for FPGA <> HPS bridges +// via brgmodrst register in Reset Manager when loading rbf. +// But it has no effect on f2sdram interface. +// f2sdram interface seems to belong to SDRAM Controller Subsystem +// rather than FPGA-to-HPS bridge. +// +// Main_MiSTer is also trying to issuing reset for f2sdram ports +// via fpgaportrst register in SDRAM Controller Subsystem when loading rbf. +// But according to the Intel's document, fpgaportrst register can be +// used to stretch the port reset. +// It seems that it cannot be used to assert the port reset. +// +// According to the Intel's document, there seems to be a reset port on +// Avalon-MM slave interface, but it cannot be found in Qsys generated HDL. +// +// To conclude, the only thing FPGA can do is not to break the transaction. +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +// Purpose: +// To prevent the issue, this module completes ongoing transaction +// on behalf of user logic, when reset is asserted. +// +// Usage: +// Insert this module into the bus line between +// f2sdram (Avalon-MM slave) and user logic (Avalon-MM master). +// +// Notice: +// Asynchronous reset request is not supported. +// Please feed reset request synchronized to clock. +// +module f2sdram_safe_terminator #( + parameter DATA_WIDTH = 64, + parameter BURSTCOUNT_WIDTH = 8 +) ( + // clk should be the same as one provided to f2sdram port + // clk should not be stop when reset is asserted + input clk, + // rst_req_sync should be synchronized to clk + // Asynchronous reset request is not supported + input rst_req_sync, + + // Master port: connecting to Alavon-MM slave(f2sdram) + input waitrequest_master, + output [BURSTCOUNT_WIDTH-1:0] burstcount_master, + output [ADDRESS_WITDH-1:0] address_master, + input [DATA_WIDTH-1:0] readdata_master, + input readdatavalid_master, + output read_master, + output [DATA_WIDTH-1:0] writedata_master, + output [BYTEENABLE_WIDTH-1:0] byteenable_master, + output write_master, + + // Slave port: connecting to Alavon-MM master(user logic) + output waitrequest_slave, + input [BURSTCOUNT_WIDTH-1:0] burstcount_slave, + input [ADDRESS_WITDH-1:0] address_slave, + output [DATA_WIDTH-1:0] readdata_slave, + output readdatavalid_slave, + input read_slave, + input [DATA_WIDTH-1:0] writedata_slave, + input [BYTEENABLE_WIDTH-1:0] byteenable_slave, + input write_slave +); + + localparam BYTEENABLE_WIDTH = DATA_WIDTH/8; + localparam ADDRESS_WITDH = 32-$clog2(BYTEENABLE_WIDTH); + + /* + * Capture init reset deaseert + */ + reg init_reset_deasserted = 1'b0; + + always_ff @(posedge clk) begin + if (!rst_req_sync) begin + init_reset_deasserted <= 1'b1; + end + end + + /* + * Lock stage + */ + reg lock_stage = 1'b0; + + always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + lock_stage <= 1'b1; + end + end else begin + // Reset deassert + lock_stage <= 1'b0; + end + end + + /* + * Write burst transaction observer + */ + reg state_write = 1'b0; + wire next_state_write; + + wire burst_write_start = !state_write && next_state_write; + wire valid_write_data = state_write && !waitrequest_master; + wire burst_write_end = state_write && (write_burstcounter == write_burstcount_latch - 1'd1); + wire valid_non_burst_write = !state_write && write_slave && (burstcount_slave == 1) && !waitrequest_master; + + reg [BURSTCOUNT_WIDTH-1:0] write_burstcounter = 0; + reg [BURSTCOUNT_WIDTH-1:0] write_burstcount_latch = 0; + reg [ADDRESS_WITDH-1:0] write_address_latch = 0; + + always_ff @(posedge clk) begin + state_write <= next_state_write; + + if (burst_write_start) begin + write_burstcounter <= waitrequest_master ? 1'd0 : 1'd1; + write_burstcount_latch <= burstcount_slave; + write_address_latch <= address_slave; + end else if (valid_write_data) begin + write_burstcounter <= write_burstcounter + 1'd1; + end + end + + always_comb begin + if (!state_write) begin + if (valid_non_burst_write) + next_state_write = 1'b0; + else if (write_slave) + next_state_write = 1'b1; + else + next_state_write = 1'b0; + end else begin + if (burst_write_end) + next_state_write = 1'b0; + else + next_state_write = 1'b1; + end + end + + /* + * Safe terminating burst writing + */ + wire on_write_transaction = state_write && next_state_write; + wire on_start_write_transaction = !state_write && next_state_write; + reg write_terminating = 1'b0; + reg write_terminated = 1'b0; + + reg [BURSTCOUNT_WIDTH-1:0] write_terminate_burstcount_latch = 0; + reg [ADDRESS_WITDH-1:0] write_terminate_address_latch = 0; + reg [BURSTCOUNT_WIDTH-1:0] write_terminate_counter = 0; + + always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + if (!lock_stage) begin + if (on_write_transaction) begin + write_terminating <= 1'b1; + write_terminate_burstcount_latch <= write_burstcount_latch; + write_terminate_address_latch <= write_address_latch; + write_terminate_counter <= waitrequest_master ? write_burstcounter : write_burstcounter + 1'd1; + end else if (on_start_write_transaction) begin + if (valid_non_burst_write) begin + write_terminated <= 1'b1; + end else begin + write_terminating <= 1'b1; + write_terminate_burstcount_latch <= burstcount_slave; + write_terminate_address_latch <= address_slave; + write_terminate_counter <= waitrequest_master ? 1'd0 : 1'd1; + end + end else begin + write_terminated <= 1'b1; + end + end + end + end else begin + // Reset deassert + if (!write_terminating) begin + write_terminated <= 1'b0; + end + end + + if (write_terminating) begin + // Continue write transaction until the end + if (!waitrequest_master) begin + write_terminate_counter <= write_terminate_counter + 1'd1; + end + + if (write_terminate_counter == write_terminate_burstcount_latch - 'd1) begin + write_terminating <= 1'b0; + write_terminated <= 1'b1; + end + end + end + + /* + * Safe terminating burst reading + */ + reg [BURSTCOUNT_WIDTH-1:0] read_burstcount_latch = 0; + reg [ADDRESS_WITDH-1:0] read_address_latch = 0; + reg read_terminating = 1'b0; + reg read_siganl_in_terminating = 1'b0; + + always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + if (!lock_stage) begin + if (read_slave && waitrequest_master) begin + // Need to keep read signal, burstcount and address until waitrequest_master deasserted + read_siganl_in_terminating <= 1'b1; + read_burstcount_latch <= burstcount_slave; + read_address_latch <= address_slave; + read_terminating <= 1'b1; + end else if (!on_write_transaction && !on_start_write_transaction) begin + // Even not knowing reading is in progress or not, + // if it is in progress, it will finish at some point, and no need to do something. + // Assume that reading is in progress when we are not on write transaction. + read_siganl_in_terminating <= 0; + read_burstcount_latch <= 1; + read_address_latch <= 0; + read_siganl_in_terminating <= 0; + read_terminating <= 1; + end + end else begin + if (!waitrequest_master) begin + read_siganl_in_terminating <= 1'b0; + end + end + end + end else begin + // Reset deassert + read_terminating <= 1'b0; + end + end + + /* + * Bus mux depending on the stage. + */ + always_comb begin + if (read_terminating) begin + burstcount_master = read_burstcount_latch; + address_master = read_address_latch; + read_master = read_siganl_in_terminating; + writedata_master = 0; + byteenable_master = '1; // all 1 + write_master = 0; + end else if (write_terminating) begin + burstcount_master = write_terminate_burstcount_latch; + address_master = write_terminate_address_latch; + read_master = 0; + writedata_master = 0; + byteenable_master = '1; // all 1 + write_master = 1; + end else if (write_terminated) begin + burstcount_master = 1; + address_master = 0; + read_master = 0; + writedata_master = 0; + byteenable_master = 0; + write_master = 0; + end else begin + burstcount_master = burstcount_slave; + address_master = address_slave; + read_master = read_slave; + writedata_master = writedata_slave; + byteenable_master = byteenable_slave; + write_master = write_slave; + end + end + + // Just passing through master to slave + assign waitrequest_slave = waitrequest_master; + assign readdata_slave = readdata_master; + assign readdatavalid_slave = readdatavalid_master; + +endmodule diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv index 775a560..4a0a13d 100644 --- a/sys/hdmi_config.sv +++ b/sys/hdmi_config.sv @@ -111,32 +111,32 @@ wire [15:0] init_data[82] = {8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 - {8'h18, ypbpr ? 8'h88 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. - {8'h19, ypbpr ? 8'h2E : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide. - {8'h1A, ypbpr ? 8'h18 : 8'h00}, // CSC Channel A. - {8'h1B, ypbpr ? 8'h93 : 8'h00}, - {8'h1C, ypbpr ? 8'h1F : 8'h00}, - {8'h1D, ypbpr ? 8'h3F : 8'h00}, - {8'h1E, ypbpr ? 8'h08 : 8'h01}, - {8'h1F, 8'h00}, + {8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. + {8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide. + {8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A. + {8'h1B, ypbpr ? 8'h3F : 8'h00}, + {8'h1C, ypbpr ? 8'h1E : 8'h00}, + {8'h1D, ypbpr ? 8'hE2 : 8'h00}, + {8'h1E, ypbpr ? 8'h07 : 8'h01}, + {8'h1F, ypbpr ? 8'hE7 : 8'h00}, - {8'h20, ypbpr ? 8'h03 : 8'h00}, // CSC Channel B. - {8'h21, ypbpr ? 8'h67 : 8'h00}, - {8'h22, ypbpr ? 8'h0B : limited[0] ? 8'h0D : 8'h0E}, - {8'h23, ypbpr ? 8'h71 : limited[0] ? 8'hBC : 8'hFE}, + {8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B. + {8'h21, ypbpr ? 8'h1C : 8'h00}, + {8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E}, + {8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE}, {8'h24, ypbpr ? 8'h01 : 8'h00}, - {8'h25, ypbpr ? 8'h28 : 8'h00}, - {8'h26, ypbpr ? 8'h00 : 8'h01}, + {8'h25, ypbpr ? 8'h91 : 8'h00}, + {8'h26, ypbpr ? 8'h01 : 8'h01}, {8'h27, 8'h00}, - {8'h28, ypbpr ? 8'h1E : 8'h00}, // CSC Channel C. - {8'h29, ypbpr ? 8'h21 : 8'h00}, - {8'h2A, ypbpr ? 8'h19 : 8'h00}, - {8'h2B, ypbpr ? 8'hB2 : 8'h00}, - {8'h2C, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E}, - {8'h2D, ypbpr ? 8'h2D : limited[0] ? 8'hBC : 8'hFE}, - {8'h2E, ypbpr ? 8'h08 : 8'h01}, - {8'h2F, 8'h00}, + {8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C. + {8'h29, ypbpr ? 8'hAE : 8'h00}, + {8'h2A, ypbpr ? 8'h1B : 8'h00}, + {8'h2B, ypbpr ? 8'h73 : 8'h00}, + {8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E}, + {8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, + {8'h2E, ypbpr ? 8'h07 : 8'h01}, + {8'h2F, ypbpr ? 8'hE7 : 8'h00}, {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. diff --git a/sys/hps_io.v b/sys/hps_io.v index 23ade3f..9431c95 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -126,7 +126,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output reg [32:0] TIMESTAMP, // UART flags - input [15:0] uart_mode, + output reg [7:0] uart_mode, + output reg [31:0] uart_speed, // ps2 keyboard emulation output ps2_kbd_clk_out, @@ -248,6 +249,8 @@ always@(posedge clk_sys) begin : uio_block reg old_status_set = 0; reg old_info = 0; reg [7:0] info_n = 0; + reg [15:0] tmp1; + reg [7:0] tmp2; old_status_set <= status_set; if(~old_status_set & status_set) begin @@ -453,9 +456,6 @@ always@(posedge clk_sys) begin : uio_block //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; - //UART flags - 'h28: io_dout <= uart_mode; - //status set 'h29: if(!byte_cnt[MAX_W:3]) begin case(byte_cnt[2:0]) @@ -479,6 +479,15 @@ always@(posedge clk_sys) begin : uio_block {gamma_wr, gamma_value} <= {1'b1,io_din[7:0]}; if (byte_cnt[1:0] == 3) byte_cnt <= 1; end + + // UART + 'h3b: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: tmp2 <= io_din[7:0]; + 2: tmp1 <= io_din; + 3: {uart_speed, uart_mode} <= {io_din, tmp1, tmp2}; + endcase + end endcase end end diff --git a/sys/mt32pi.sv b/sys/mt32pi.sv new file mode 100644 index 0000000..6704807 --- /dev/null +++ b/sys/mt32pi.sv @@ -0,0 +1,283 @@ +// +// Communication module to MT32-pi (external MIDI emulator on RPi) +// (C) 2020 Sorgelig, Kitrinx +// +// https://github.com/dwhinham/mt32-pi +// + +module mt32pi +( + input CLK_AUDIO, + + input CLK_VIDEO, + input CE_PIXEL, + input VGA_VS, + input VGA_DE, + + input [6:0] USER_IN, + output [6:0] USER_OUT, + + input reset, + input midi_tx, + output midi_rx, + + output reg [15:0] mt32_i2s_r, + output reg [15:0] mt32_i2s_l, + + output reg mt32_available, + + input mt32_mode_req, + input [1:0] mt32_rom_req, + input [7:0] mt32_sf_req, + + output reg [7:0] mt32_mode, + output reg [7:0] mt32_rom, + output reg [7:0] mt32_sf, + output reg mt32_newmode, + + output reg mt32_lcd_en, + output reg mt32_lcd_pix, + output reg mt32_lcd_update +); + +// +// Pin | USB Name | Signal +// ----+----------+-------------- +// 0 | D+ | I/O I2C_SDA / RX (midi in) +// 1 | D- | O TX (midi out) +// 2 | TX- | I I2S_WS (1 == right) +// 3 | GND_d | I I2C_SCL +// 4 | RX+ | I I2S_BCLK +// 5 | RX- | I I2S_DAT +// 6 | TX+ | - none +// + +assign USER_OUT[0] = sda_out; +assign USER_OUT[1] = midi_tx; +assign USER_OUT[6:2] = '1; + + +// +// crossed/straight cable selection +// + +generate + genvar i; + for(i = 0; i<2; i++) begin : clk_rate + wire clk_in = i ? USER_IN[6] : USER_IN[4]; + reg [4:0] cnt; + always @(posedge CLK_AUDIO) begin : clkr + reg clk_sr, clk, old_clk; + reg [4:0] cnt_tmp; + + clk_sr <= clk_in; + if (clk_sr == clk_in) clk <= clk_sr; + + if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1; + else cnt <= '1; + + old_clk <= clk; + if(~old_clk & clk) begin + cnt <= cnt_tmp; + cnt_tmp <= 0; + end + end + end + + reg crossed; + always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt); +endgenerate + +wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5]; +wire i2s_data = crossed ? USER_IN[5] : USER_IN[2]; +wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6]; +assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4]; + + +// +// i2s receiver +// + +always @(posedge CLK_AUDIO) begin : i2s_proc + reg [15:0] i2s_buf = 0; + reg [4:0] i2s_cnt = 0; + reg clk_sr; + reg i2s_clk = 0; + reg old_clk, old_ws; + reg i2s_next = 0; + + // Debounce clock + clk_sr <= i2s_bclk; + if (clk_sr == i2s_bclk) i2s_clk <= clk_sr; + + // Latch data and ws on rising edge + old_clk <= i2s_clk; + if (i2s_clk && ~old_clk) begin + + if (~i2s_cnt[4]) begin + i2s_cnt <= i2s_cnt + 1'd1; + i2s_buf[~i2s_cnt[3:0]] <= i2s_data; + end + + // Word Select will change 1 clock before the new word starts + old_ws <= i2s_ws; + if (old_ws != i2s_ws) i2s_next <= 1; + end + + if (i2s_next) begin + i2s_next <= 0; + i2s_cnt <= 0; + i2s_buf <= 0; + + if (i2s_ws) mt32_i2s_l <= i2s_buf; + else mt32_i2s_r <= i2s_buf; + end + + if (reset) begin + i2s_buf <= 0; + mt32_i2s_l <= 0; + mt32_i2s_r <= 0; + end +end + + +// +// i2c slave +// + +reg sda_out; +reg [7:0] lcd_data[1024]; +reg lcd_sz; + +reg reset_r = 0; +wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1; +wire [7:0] rom_req = {6'd0, mt32_rom_req}; + +always @(posedge CLK_AUDIO) begin : i2c_slave + reg sda_sr, scl_sr; + reg old_sda, old_scl; + reg sda, scl; + reg [7:0] tmp; + reg [3:0] cnt = 0; + reg [10:0] bcnt = 0; + reg ack; + reg i2c_rw; + reg disp, dispdata; + reg [2:0] div; + reg old_reset; + + old_reset <= reset; + if(old_reset & ~reset) sda_out <= 1; + + div <= div + 1'd1; + if(!div) begin + sda_sr <= USER_IN[0]; + if(sda_sr == USER_IN[0]) sda <= sda_sr; + old_sda <= sda; + + scl_sr <= USER_IN[3]; + if(scl_sr == USER_IN[3]) scl <= scl_sr; + old_scl <= scl; + + //start + if(old_scl & scl & old_sda & ~sda) begin + cnt <= 9; + bcnt <= 0; + ack <= 0; + i2c_rw <= 0; + disp <= 0; + dispdata <= 0; + end + + //stop + if(old_scl & scl & ~old_sda & sda) begin + cnt <= 0; + if(dispdata) begin + lcd_sz <= ~bcnt[9]; + mt32_lcd_update <= ~mt32_lcd_update; + end + end + + //data latch + if(~old_scl && scl && cnt) begin + tmp <= {tmp[6:0], sda}; + cnt <= cnt - 1'd1; + end + + if(!cnt) sda_out <= 1; + + //data set + if(old_scl && ~scl) begin + sda_out <= 1; + if(cnt == 1) begin + if(!bcnt) begin + if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin + disp <= (tmp[7:1] == 'h3c); + sda_out <= 0; + mt32_available <= 1; + ack <= 1; + i2c_rw <= tmp[0]; + bcnt <= bcnt + 1'd1; + cnt <= 10; + end + else begin + // wrong address, stop + cnt <= 0; + end + end + else if(ack) begin + if(~i2c_rw) begin + if(disp) begin + if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01); + else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp; + end + else begin + if(bcnt == 1) mt32_mode <= tmp; + if(bcnt == 2) mt32_rom <= tmp; + if(bcnt == 3) mt32_sf <= tmp; + if(bcnt == 3) mt32_newmode <= ~mt32_newmode; + end + end + if(~&bcnt) bcnt <= bcnt + 1'd1; + sda_out <= 0; + cnt <= 10; + end + end + else if(i2c_rw && ack && cnt && ~disp) begin + if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2]; + if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) reset_r <= 0; + end + end + end + + if(reset) begin + reset_r <= 1; + mt32_available <= 0; + end +end + +always @(posedge CLK_VIDEO) begin + reg old_de, old_vs; + reg [7:0] hcnt; + reg [6:0] vcnt; + reg [7:0] sh; + + if(CE_PIXEL) begin + old_de <= VGA_DE; + old_vs <= VGA_VS; + + if(~&hcnt) hcnt <= hcnt + 1'd1; + sh <= (sh << 1) | (~old_de & VGA_DE); + if(sh[7]) hcnt <= 0; + + if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & VGA_VS) vcnt <= 0; + + mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]); + mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]]; + end +end + +endmodule diff --git a/sys/sd_card.sv b/sys/sd_card.sv index 6d90015..a2aad7e 100644 --- a/sys/sd_card.sv +++ b/sys/sd_card.sv @@ -347,7 +347,14 @@ always @(posedge clk_spi) begin 'h4a: reply <= 0; // ok // CMD12: STOP_TRANSMISSION - 'h4c: reply <= 0; // ok + 'h4c: reply <= 0; // ok + + // CMD13: SEND_STATUS + 'h4d: begin + reply <= 'h00; // ok + reply0 <='h00; + reply_len <= 1; + end // CMD16: SET_BLOCKLEN 'h50: begin diff --git a/sys/spdif.v b/sys/spdif.v index d50c2da..db5027c 100644 --- a/sys/spdif.v +++ b/sys/spdif.v @@ -67,6 +67,8 @@ reg spdif_out_q; reg [5:0] parity_count_q; +reg channel_status_bit; + //----------------------------------------------------------------- // Subframe Counter //----------------------------------------------------------------- @@ -142,7 +144,7 @@ assign subframe_w[28] = 1'b0; // Valid assign subframe_w[29] = 1'b0; // Timeslots 30 = Channel status bit -assign subframe_w[30] = 1'b0; +assign subframe_w[30] = channel_status_bit ; //was constant 1'b0 enabling copy-bit; // Timeslots 31 = Even Parity bit (31:4) assign subframe_w[31] = 1'b0; @@ -150,9 +152,9 @@ assign subframe_w[31] = 1'b0; //----------------------------------------------------------------- // Preamble //----------------------------------------------------------------- -localparam PREAMBLE_Z = 8'b00010111; -localparam PREAMBLE_Y = 8'b00100111; -localparam PREAMBLE_X = 8'b01000111; +localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block +localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data +localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block reg [7:0] preamble_r; @@ -168,6 +170,15 @@ begin // Left Channel (but not start of block)? else preamble_r = PREAMBLE_X; // X(M) + + if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted + channel_status_bit = 1'b1; + else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media + channel_status_bit = 1'b1; + else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r) + channel_status_bit = 1'b1; + else + channel_status_bit = 1'b0; // everything else defaults to 0 end always @ (posedge rst_i or posedge clk_i ) diff --git a/sys/sys.qip b/sys/sys.qip index 9a28ae0..242e396 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -20,8 +20,10 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) a set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ] diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 90dc24d..46c761d 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -21,29 +21,30 @@ set_clock_groups -exclusive \ 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 -to [get_ports {AUDIO_SPDIF}] -set_false_path -to [get_ports {AUDIO_L}] -set_false_path -to [get_ports {AUDIO_R}] -set_false_path -to {cfg[*]} +set_false_path -to [get_ports {LED_*}] +set_false_path -to [get_ports {VGA_*}] +set_false_path -to [get_ports {AUDIO_SPDIF}] +set_false_path -to [get_ports {AUDIO_L}] +set_false_path -to [get_ports {AUDIO_R}] +set_false_path -to {cfg[*]} set_false_path -from {cfg[*]} set_false_path -from {VSET[*]} -set_false_path -to {wcalc[*] hcalc[*]} -set_false_path -to {width[*] height[*]} +set_false_path -to {wcalc[*] hcalc[*]} +set_false_path -to {width[*] height[*]} set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 -set_false_path -to {*_osd|v_cnt*} -set_false_path -to {*_osd|v_osd_start*} -set_false_path -to {*_osd|v_info_start*} -set_false_path -to {*_osd|h_osd_start*} + +set_false_path -to {*_osd|v_cnt*} +set_false_path -to {*_osd|v_osd_start*} +set_false_path -to {*_osd|v_info_start*} +set_false_path -to {*_osd|h_osd_start*} set_false_path -from {*_osd|v_osd_start*} set_false_path -from {*_osd|v_info_start*} set_false_path -from {*_osd|h_osd_start*} set_false_path -from {*_osd|rot*} set_false_path -from {*_osd|dsp_width*} -set_false_path -to {*_osd|half} +set_false_path -to {*_osd|half} set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} @@ -51,4 +52,11 @@ set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} -set_false_path -from {aflt_* acx* acy* areset*} +set_false_path -from {aflt_* acx* acy* areset* arc*} +set_false_path -from {vs_line*} + +set_false_path -from {ascal|o_ihsize*} +set_false_path -from {ascal|o_ivsize*} +set_false_path -from {ascal|o_format*} +set_false_path -from {ascal|o_hdown} +set_false_path -from {ascal|o_vdown} diff --git a/sys/sys_top.v b/sys/sys_top.v index c795a6b..d6a6557 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -287,7 +287,7 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp reg [15:0] cfg; reg cfg_set = 0; -wire vga_fb = cfg[12]; +wire vga_fb = cfg[12] | vga_force_scaler; wire [1:0] hdmi_limited = {cfg[11],cfg[8]}; `ifdef DEBUG_NOHDMI @@ -303,7 +303,7 @@ wire ypbpr_en = cfg[5]; wire io_osd_vga = io_ss1 & ~io_ss2; `ifndef DUAL_SDRAM wire sog = cfg[9]; - wire vga_scaler = cfg[2]; + wire vga_scaler = cfg[2] | vga_force_scaler; `endif reg cfg_custom_t = 0; @@ -316,7 +316,7 @@ reg [6:0] coef_addr; reg [8:0] coef_data; reg coef_wr = 0; -wire [7:0] ARX, ARY; +wire[11:0] ARX, ARY; reg [11:0] VSET = 0, HSET = 0; reg FREESCALE = 0; reg [2:0] scaler_flt; @@ -337,6 +337,10 @@ reg [23:0] acy0 = -24'd6216759; reg [23:0] acy1 = 24'd6143386; reg [23:0] acy2 = -24'd2023767; reg areset = 0; +reg [11:0] arc1x = 0; +reg [11:0] arc1y = 0; +reg [11:0] arc2x = 0; +reg [11:0] arc2y = 0; always@(posedge clk_sys) begin reg [7:0] cmd; @@ -455,6 +459,15 @@ always@(posedge clk_sys) begin 14: acy2[23:16] <= io_din[7:0]; endcase end + if(cmd == 'h3A) begin + cnt <= cnt + 1'd1; + case(cnt[3:0]) + 0: arc1x <= io_din[11:0]; + 1: arc1y <= io_din[11:0]; + 2: arc2x <= io_din[11:0]; + 3: arc2y <= io_din[11:0]; + endcase + end end end @@ -778,9 +791,30 @@ always @(posedge clk_vid) begin reg [11:0] videoh; reg [11:0] height; reg [11:0] width; + reg [11:0] arx; + reg [11:0] ary; height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT; width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH; + + if(!ARY) begin + if(ARX == 1) begin + arx <= arc1x; + ary <= arc1y; + end + else if(ARX == 2) begin + arx <= arc2x; + ary <= arc2y; + end + else begin + arx <= 0; + ary <= 0; + end + end + else begin + arx <= ARX; + ary <= ARY; + end state <= state + 1'd1; case(state) @@ -791,18 +825,20 @@ always @(posedge clk_vid) begin vmax <= LFB_VMAX; state<= 0; end - else if(ARX && ARY && !FREESCALE) begin - wcalc <= (height*ARX)/ARY; - hcalc <= (width*ARY)/ARX; - end - else begin + else if(FREESCALE || !arx || !ary) begin wcalc <= width; hcalc <= height; end + else begin + wcalc <= (height*arx)/ary; + hcalc <= (width*ary)/arx; + end + 6: begin videow <= (wcalc > width) ? width : wcalc[11:0]; videoh <= (hcalc > height) ? height : hcalc[11:0]; end + 7: begin hmin <= ((WIDTH - videow)>>1); hmax <= ((WIDTH - videow)>>1) + videow - 1'd1; @@ -1174,24 +1210,45 @@ wire vga_cs_osd; csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); `ifndef DUAL_SDRAM - wire [23:0] vga_o; - vga_out vga_out + wire [23:0] vgas_o; + wire vgas_hs, vgas_vs, vgas_cs; + vga_out vga_scaler_out ( - .ypbpr_full(0), + .clk(clk_hdmi), .ypbpr_en(ypbpr_en), - .dout(vga_o), - .din((vga_fb | vga_scaler) ? {24{hdmi_de_osd}} & hdmi_data_osd : vga_data_osd) + .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 vs1 = (vga_fb | vga_scaler) ? hdmi_vs_osd : vga_vs_osd; - wire hs1 = (vga_fb | vga_scaler) ? hdmi_hs_osd : vga_hs_osd; - wire cs1 = (vga_fb | vga_scaler) ? hdmi_cs_osd : vga_cs_osd; + wire [23:0] vga_o; + wire vga_hs, vga_vs, vga_cs; + 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), + .din(vga_data_osd), + .hsync_o(vga_hs), + .vsync_o(vga_vs), + .csync_o(vga_cs) + ); - assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : csync_en ? 1'b1 : ~vs1; - assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : csync_en ? ~cs1 : ~hs1; - assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : vga_o[23:18]; - assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : vga_o[15:10]; - assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : vga_o[7:2]; + wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs; + + assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en; + assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs); + assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18]; + assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10]; + assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ; `endif reg video_sync = 0; @@ -1335,6 +1392,7 @@ wire [7:0] r_out, g_out, b_out, hr_out, hg_out, hb_out; wire vs_fix, hs_fix, de_emu, vs_emu, hs_emu, f1; wire hvs_fix, hhs_fix, hde_emu; wire clk_vid, ce_pix, clk_ihdmi, ce_hpix; +wire vga_force_scaler; `ifdef USE_DDRAM wire ram_clk; @@ -1422,6 +1480,7 @@ emu emu .VGA_VS(vs_emu), .VGA_DE(de_emu), .VGA_F1(f1), + .VGA_SCALER(vga_force_scaler), .CLK_VIDEO(clk_vid), .CE_PIXEL(ce_pix), diff --git a/sys/sysmem.sv b/sys/sysmem.sv index c90395e..8c17e86 100644 --- a/sys/sysmem.sv +++ b/sys/sysmem.sv @@ -44,41 +44,182 @@ module sysmem_lite assign reset_out = ~init_reset_n | ~hps_h2f_reset_n | reset_core_req; +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram1 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram1_address; +wire [7:0] f2h_ram1_burstcount; +wire f2h_ram1_waitrequest; +wire [63:0] f2h_ram1_readdata; +wire f2h_ram1_readdatavalid; +wire f2h_ram1_read; +wire [63:0] f2h_ram1_writedata; +wire [7:0] f2h_ram1_byteenable; +wire f2h_ram1_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_1 = 1'b1; +always @(posedge ram1_clk) begin + ram1_reset_0 <= reset_out; + ram1_reset_1 <= ram1_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram1 +( + .clk (ram1_clk), + .rst_req_sync (ram1_reset_1), + + .waitrequest_slave (ram1_waitrequest), + .burstcount_slave (ram1_burstcount), + .address_slave (ram1_address), + .readdata_slave (ram1_readdata), + .readdatavalid_slave (ram1_readdatavalid), + .read_slave (ram1_read), + .writedata_slave (ram1_writedata), + .byteenable_slave (ram1_byteenable), + .write_slave (ram1_write), + + .waitrequest_master (f2h_ram1_waitrequest), + .burstcount_master (f2h_ram1_burstcount), + .address_master (f2h_ram1_address), + .readdata_master (f2h_ram1_readdata), + .readdatavalid_master (f2h_ram1_readdatavalid), + .read_master (f2h_ram1_read), + .writedata_master (f2h_ram1_writedata), + .byteenable_master (f2h_ram1_byteenable), + .write_master (f2h_ram1_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram2 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram2_address; +wire [7:0] f2h_ram2_burstcount; +wire f2h_ram2_waitrequest; +wire [63:0] f2h_ram2_readdata; +wire f2h_ram2_readdatavalid; +wire f2h_ram2_read; +wire [63:0] f2h_ram2_writedata; +wire [7:0] f2h_ram2_byteenable; +wire f2h_ram2_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_1 = 1'b1; +always @(posedge ram2_clk) begin + ram2_reset_0 <= reset_out; + ram2_reset_1 <= ram2_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram2 +( + .clk (ram2_clk), + .rst_req_sync (ram2_reset_1), + + .waitrequest_slave (ram2_waitrequest), + .burstcount_slave (ram2_burstcount), + .address_slave (ram2_address), + .readdata_slave (ram2_readdata), + .readdatavalid_slave (ram2_readdatavalid), + .read_slave (ram2_read), + .writedata_slave (ram2_writedata), + .byteenable_slave (ram2_byteenable), + .write_slave (ram2_write), + + .waitrequest_master (f2h_ram2_waitrequest), + .burstcount_master (f2h_ram2_burstcount), + .address_master (f2h_ram2_address), + .readdata_master (f2h_ram2_readdata), + .readdatavalid_master (f2h_ram2_readdatavalid), + .read_master (f2h_ram2_read), + .writedata_master (f2h_ram2_writedata), + .byteenable_master (f2h_ram2_byteenable), + .write_master (f2h_ram2_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_vbuf //// +//////////////////////////////////////////////////////// +wire [27:0] f2h_vbuf_address; +wire [7:0] f2h_vbuf_burstcount; +wire f2h_vbuf_waitrequest; +wire [127:0] f2h_vbuf_readdata; +wire f2h_vbuf_readdatavalid; +wire f2h_vbuf_read; +wire [127:0] f2h_vbuf_writedata; +wire [15:0] f2h_vbuf_byteenable; +wire f2h_vbuf_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_1 = 1'b1; +always @(posedge vbuf_clk) begin + vbuf_reset_0 <= reset_out; + vbuf_reset_1 <= vbuf_reset_0; +end + +f2sdram_safe_terminator #(128, 8) f2sdram_safe_terminator_vbuf +( + .clk (vbuf_clk), + .rst_req_sync (vbuf_reset_1), + + .waitrequest_slave (vbuf_waitrequest), + .burstcount_slave (vbuf_burstcount), + .address_slave (vbuf_address), + .readdata_slave (vbuf_readdata), + .readdatavalid_slave (vbuf_readdatavalid), + .read_slave (vbuf_read), + .writedata_slave (vbuf_writedata), + .byteenable_slave (vbuf_byteenable), + .write_slave (vbuf_write), + + .waitrequest_master (f2h_vbuf_waitrequest), + .burstcount_master (f2h_vbuf_burstcount), + .address_master (f2h_vbuf_address), + .readdata_master (f2h_vbuf_readdata), + .readdatavalid_master (f2h_vbuf_readdatavalid), + .read_master (f2h_vbuf_read), + .writedata_master (f2h_vbuf_writedata), + .byteenable_master (f2h_vbuf_byteenable), + .write_master (f2h_vbuf_write) +); + +//////////////////////////////////////////////////////// +//// HPS <> FPGA interfaces //// +//////////////////////////////////////////////////////// sysmem_HPS_fpga_interfaces fpga_interfaces ( .f2h_cold_rst_req_n (~reset_hps_cold_req), .f2h_warm_rst_req_n (~reset_hps_warm_req), .h2f_user0_clk (clock), .h2f_rst_n (hps_h2f_reset_n), .f2h_sdram0_clk (vbuf_clk), - .f2h_sdram0_ADDRESS (vbuf_address), - .f2h_sdram0_BURSTCOUNT (vbuf_burstcount), - .f2h_sdram0_WAITREQUEST (vbuf_waitrequest), - .f2h_sdram0_READDATA (vbuf_readdata), - .f2h_sdram0_READDATAVALID (vbuf_readdatavalid), - .f2h_sdram0_READ (vbuf_read), - .f2h_sdram0_WRITEDATA (vbuf_writedata), - .f2h_sdram0_BYTEENABLE (vbuf_byteenable), - .f2h_sdram0_WRITE (vbuf_write), + .f2h_sdram0_ADDRESS (f2h_vbuf_address), + .f2h_sdram0_BURSTCOUNT (f2h_vbuf_burstcount), + .f2h_sdram0_WAITREQUEST (f2h_vbuf_waitrequest), + .f2h_sdram0_READDATA (f2h_vbuf_readdata), + .f2h_sdram0_READDATAVALID (f2h_vbuf_readdatavalid), + .f2h_sdram0_READ (f2h_vbuf_read), + .f2h_sdram0_WRITEDATA (f2h_vbuf_writedata), + .f2h_sdram0_BYTEENABLE (f2h_vbuf_byteenable), + .f2h_sdram0_WRITE (f2h_vbuf_write), .f2h_sdram1_clk (ram1_clk), - .f2h_sdram1_ADDRESS (ram1_address), - .f2h_sdram1_BURSTCOUNT (ram1_burstcount), - .f2h_sdram1_WAITREQUEST (ram1_waitrequest), - .f2h_sdram1_READDATA (ram1_readdata), - .f2h_sdram1_READDATAVALID (ram1_readdatavalid), - .f2h_sdram1_READ (ram1_read), - .f2h_sdram1_WRITEDATA (ram1_writedata), - .f2h_sdram1_BYTEENABLE (ram1_byteenable), - .f2h_sdram1_WRITE (ram1_write), + .f2h_sdram1_ADDRESS (f2h_ram1_address), + .f2h_sdram1_BURSTCOUNT (f2h_ram1_burstcount), + .f2h_sdram1_WAITREQUEST (f2h_ram1_waitrequest), + .f2h_sdram1_READDATA (f2h_ram1_readdata), + .f2h_sdram1_READDATAVALID (f2h_ram1_readdatavalid), + .f2h_sdram1_READ (f2h_ram1_read), + .f2h_sdram1_WRITEDATA (f2h_ram1_writedata), + .f2h_sdram1_BYTEENABLE (f2h_ram1_byteenable), + .f2h_sdram1_WRITE (f2h_ram1_write), .f2h_sdram2_clk (ram2_clk), - .f2h_sdram2_ADDRESS (ram2_address), - .f2h_sdram2_BURSTCOUNT (ram2_burstcount), - .f2h_sdram2_WAITREQUEST (ram2_waitrequest), - .f2h_sdram2_READDATA (ram2_readdata), - .f2h_sdram2_READDATAVALID (ram2_readdatavalid), - .f2h_sdram2_READ (ram2_read), - .f2h_sdram2_WRITEDATA (ram2_writedata), - .f2h_sdram2_BYTEENABLE (ram2_byteenable), - .f2h_sdram2_WRITE (ram2_write) + .f2h_sdram2_ADDRESS (f2h_ram2_address), + .f2h_sdram2_BURSTCOUNT (f2h_ram2_burstcount), + .f2h_sdram2_WAITREQUEST (f2h_ram2_waitrequest), + .f2h_sdram2_READDATA (f2h_ram2_readdata), + .f2h_sdram2_READDATAVALID (f2h_ram2_readdatavalid), + .f2h_sdram2_READ (f2h_ram2_read), + .f2h_sdram2_WRITEDATA (f2h_ram2_writedata), + .f2h_sdram2_BYTEENABLE (f2h_ram2_byteenable), + .f2h_sdram2_WRITE (f2h_ram2_write) ); wire hps_h2f_reset_n; diff --git a/sys/vga_out.sv b/sys/vga_out.sv index e316000..43927b2 100644 --- a/sys/vga_out.sv +++ b/sys/vga_out.sv @@ -1,44 +1,20 @@ module vga_out ( - input ypbpr_full, + input clk, input ypbpr_en, - input [23:0] din, - output [23:0] dout -); + input hsync, + input vsync, + input csync, -wire [5:0] yuv_full[225] = '{ - 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, - 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, - 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, - 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, - 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, - 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, - 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, - 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, - 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, - 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, - 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, - 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, - 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, - 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, - 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, - 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, - 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, - 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, - 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, - 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, - 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, - 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, - 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, - 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, - 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, - 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, - 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, - 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, - 6'd63 -}; + input [23:0] din, + output [23:0] dout, + + output reg hsync_o, + output reg vsync_o, + output reg csync_o +); wire [5:0] red = din[23:18]; wire [5:0] green = din[15:10]; @@ -49,17 +25,27 @@ wire [5:0] blue = din[7:2]; // 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) -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}); -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}); -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}); +reg [18:0] y_2, pb_2, pr_2; +reg [7:0] y, pb, pr; +reg [23:0] din2, din3; +reg hsync2, vsync2, csync2; +always @(posedge clk) begin + y_2 <= 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); + pb_2 <= 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}); + pr_2 <= 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}); -wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; -wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; -wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + 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]; -assign dout[23:16] = ypbpr_en ? {(ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]), 2'b00} : din[23:16]; -assign dout[15:8] = ypbpr_en ? {(ypbpr_full ? yuv_full[y -8'd16] : y[7:2]), 2'b00} : din[15:8]; -assign dout[7:0] = ypbpr_en ? {(ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]), 2'b00} : din[7:0]; + hsync_o <= hsync2; hsync2 <= hsync; + vsync_o <= vsync2; vsync2 <= vsync; + csync_o <= csync2; csync2 <= csync; + din2 <= din; + din3 <= din2; +end + +assign dout = ypbpr_en ? {pr, y, pb} : din3; endmodule