From 86fec2eb570b4abb4e7d3abcae6c7bbff91ebc83 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Wed, 6 Jan 2021 02:23:38 +0800 Subject: [PATCH] Update sys. Support for custom AR. Fix overlapped OSD options. --- SMS.sv | 38 ++++--- sys/ascal.vhd | 9 +- sys/hdmi_config.sv | 44 ++++---- sys/hps_io.v | 89 ++++++++++----- sys/mt32pi.sv | 273 +++++++++++++++++++++++++++++++++++++++++++++ sys/sd_card.sv | 9 +- sys/sys.qip | 1 + sys/sys_top.sdc | 6 + sys/sys_top.v | 69 +++++++++--- 9 files changed, 458 insertions(+), 80 deletions(-) create mode 100644 sys/mt32pi.sv diff --git a/SMS.sv b/SMS.sv index de1ba3f..6349d4f 100644 --- a/SMS.sv +++ b/SMS.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,7 @@ module emu output VGA_DE, // = ~(VBlank | HBlank) output VGA_F1, output [1:0] VGA_SL, + output VGA_SCALER, // Force VGA scaler output LED_USER, // 1 - ON, 0 - OFF. @@ -132,27 +133,37 @@ assign {UART_RTS, UART_TXD, UART_DTR} = 0; assign {SD_SCK, SD_MOSI, SD_CS} = '1; assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = '0; -assign LED_USER = cart_download | bk_state | (status[23] & bk_pending); -assign LED_DISK = 0 ; -assign LED_POWER = 0 ; +assign LED_USER = cart_download | bk_state | (status[25] & bk_pending); +assign LED_DISK = 0; +assign LED_POWER = 0; assign BUTTONS = 0; +assign VGA_SCALER= 0; -assign VIDEO_ARX = status[9] ? 8'd16 : gg ? 8'd10 : 8'd4; -assign VIDEO_ARY = status[9] ? 8'd9 : gg ? 8'd9 : 8'd3; +wire [1:0] ar = status[27:26]; + +assign VIDEO_ARX = (!ar) ? 12'd4 : (ar - 1'd1); +assign VIDEO_ARY = (!ar) ? 12'd3 : 12'd0; + +// Status Bit Map: +// Upper Lower +// 0 1 2 3 4 5 6 +// 01234567890123456789012345678901 23456789012345678901234567890123 +// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV +// XXXXXXXXXXXXXXXXXXXXXXXXXXXX `include "build_id.v" parameter CONF_STR = { "SMS;;", "-;", - "FS,SMSSG;", - "FS,GG;", + "FS1,SMSSG;", + "FS2,GG;", "-;", "C,Cheats;", "H1OO,Cheats enabled,ON,OFF;", "-;", "D0R6,Load Backup RAM;", "D0R7,Save Backup RAM;", - "D0ON,Autosave,OFF,ON;", + "D0OP,Autosave,OFF,ON;", "-;", "OA,Region,US/UE,Japan;", @@ -163,8 +174,7 @@ parameter CONF_STR = { "P1,Audio & Video;", "P1-;", "P1O2,TV System,NTSC,PAL;", - "H2P1O9,Aspect ratio,4:3,16:9;", - "h2P1O9,Aspect ratio,10:9,16:9;", + "P1OQR,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", "P1O35,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", "P1-;", "P1OD,Border,No,Yes;", @@ -213,7 +223,7 @@ wire reset = RESET | status[0] | buttons[1] | cart_download | bk_loading; wire [6:0] joy[4], joy_0, joy_1; wire [7:0] joy0_x,joy0_y,joy1_x,joy1_y; wire [1:0] buttons; -wire [31:0] status; +wire [63:0] status; wire ioctl_wr; wire [24:0] ioctl_addr; @@ -741,7 +751,7 @@ always @(posedge clk_sys) begin end wire bk_load = status[6]; -wire bk_save = status[7] | (bk_pending & OSD_STATUS && status[23]); +wire bk_save = status[7] | (bk_pending & OSD_STATUS && status[25]); reg bk_loading = 0; reg bk_state = 0; 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/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 e78808e..9431c95 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -105,10 +105,13 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) // ARM -> FPGA download output reg ioctl_download = 0, // signal indicating an active download - output reg [7:0] ioctl_index, // menu index used to upload the file + output reg [15:0] ioctl_index, // menu index used to upload the file output reg ioctl_wr, output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2 output reg [DW:0] ioctl_dout, + output reg ioctl_upload = 0, // signal indicating an active upload + input [DW:0] ioctl_din, + output reg ioctl_rd, output reg [31:0] ioctl_file_ext, input ioctl_wait, @@ -123,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, @@ -173,7 +177,7 @@ reg [15:0] io_dout; assign HPS_BUS[37] = ioctl_wait; assign HPS_BUS[36] = clk_sys; assign HPS_BUS[32] = io_wide; -assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : io_dout; +assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : fp_enable ? fp_dout : io_dout; reg [15:0] cfg; assign buttons = cfg[1:0]; @@ -234,7 +238,7 @@ wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[1 reg [MAX_W:0] byte_cnt; -always@(posedge clk_sys) begin +always@(posedge clk_sys) begin : uio_block reg [15:0] cmd; reg [2:0] b_wr; reg [3:0] stick_idx; @@ -245,6 +249,8 @@ always@(posedge clk_sys) begin 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 @@ -450,9 +456,6 @@ always@(posedge clk_sys) begin //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]) @@ -476,6 +479,15 @@ always@(posedge clk_sys) begin {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 @@ -551,18 +563,20 @@ endgenerate /////////////////////////////// DOWNLOADING /////////////////////////////// -localparam UIO_FILE_TX = 8'h53; -localparam UIO_FILE_TX_DAT = 8'h54; -localparam UIO_FILE_INDEX = 8'h55; -localparam UIO_FILE_INFO = 8'h56; +localparam FIO_FILE_TX = 8'h53; +localparam FIO_FILE_TX_DAT = 8'h54; +localparam FIO_FILE_INDEX = 8'h55; +localparam FIO_FILE_INFO = 8'h56; -always@(posedge clk_sys) begin +reg [15:0] fp_dout; +always@(posedge clk_sys) begin : fio_block reg [15:0] cmd; reg [2:0] cnt; reg has_cmd; reg [26:0] addr; reg wr; + ioctl_rd <= 0; ioctl_wr <= wr; wr <= 0; @@ -577,7 +591,7 @@ always@(posedge clk_sys) begin end else begin case(cmd) - UIO_FILE_INFO: + FIO_FILE_INFO: if(~cnt[1]) begin case(cnt) 0: ioctl_file_ext[31:16] <= io_din; @@ -586,29 +600,54 @@ always@(posedge clk_sys) begin cnt <= cnt + 1'd1; end - UIO_FILE_INDEX: + FIO_FILE_INDEX: begin - ioctl_index <= io_din[7:0]; + ioctl_index <= io_din[15:0]; end - UIO_FILE_TX: + FIO_FILE_TX: begin - if(io_din[7:0]) begin - addr <= 0; - ioctl_download <= 1; - end else begin - ioctl_addr <= addr; - ioctl_download <= 0; - end + cnt <= cnt + 1'd1; + case(cnt) + 0: if(io_din[7:0] == 8'hAA) begin + ioctl_addr <= 0; + ioctl_upload <= 1; + ioctl_rd <= 1; + end + else if(io_din[7:0]) begin + addr <= 0; + ioctl_download <= 1; + end + else begin + if(ioctl_download) ioctl_addr <= addr; + ioctl_download <= 0; + ioctl_upload <= 0; + end + + 1: begin + ioctl_addr[15:0] <= io_din; + addr[15:0] <= io_din; + end + + 2: begin + ioctl_addr[26:16] <= io_din[10:0]; + addr[26:16] <= io_din[10:0]; + end + endcase end - UIO_FILE_TX_DAT: - begin + FIO_FILE_TX_DAT: + if(ioctl_download) begin ioctl_addr <= addr; ioctl_dout <= io_din[DW:0]; wr <= 1; addr <= addr + (WIDE ? 2'd2 : 2'd1); end + else begin + ioctl_addr <= ioctl_addr + (WIDE ? 2'd2 : 2'd1); + fp_dout <= ioctl_din; + ioctl_rd <= 1; + end endcase end end diff --git a/sys/mt32pi.sv b/sys/mt32pi.sv new file mode 100644 index 0000000..22a55f2 --- /dev/null +++ b/sys/mt32pi.sv @@ -0,0 +1,273 @@ +// +// 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 +// 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 = 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 +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; + + 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/sys.qip b/sys/sys.qip index 9a28ae0..ac810d5 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -20,6 +20,7 @@ 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) ddr_svc.sv ] diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 90dc24d..6e8fd80 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -52,3 +52,9 @@ set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] 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 {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 bfddc8f..f4d0029 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 @@ -518,12 +531,11 @@ always @(posedge FPGA_CLK2_50) begin resetd2 <= resetd; end -wire clk_100m; -wire clk_pal = FPGA_CLK3_50; - //////////////////// SYSTEM MEMORY & SCALER ///////////////////////// wire reset; +wire clk_100m; + sysmem_lite sysmem ( //Reset/Clock @@ -613,6 +625,8 @@ ddr_svc ddr_svc .ch1_ready(pal_wr) ); +wire clk_pal = clk_audio; + wire [27:0] vbuf_address; wire [7:0] vbuf_burstcount; @@ -777,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) @@ -790,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; @@ -842,12 +879,14 @@ wire pal_wr; reg [28:0] pal_addr; reg pal_req = 0; always @(posedge clk_pal) begin - reg old_vs; + reg old_vs1, old_vs2; pal_addr <= LFB_BASE[31:3] - 29'd512; - old_vs <= hdmi_vs; - if(~old_vs & hdmi_vs & ~FB_FMT[2] & FB_FMT[1] & FB_FMT[0] & FB_EN) pal_req <= ~pal_req; + old_vs1 <= hdmi_vs; + old_vs2 <= old_vs1; + + if(~old_vs2 & old_vs1 & ~FB_FMT[2] & FB_FMT[1] & FB_FMT[0] & FB_EN) pal_req <= ~pal_req; end @@ -1332,6 +1371,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; @@ -1419,6 +1459,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),