diff --git a/Gameboy.sv b/Gameboy.sv index a44641b..2fd7df8 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -272,7 +272,7 @@ wire [15:0] ioctl_dout; wire ioctl_wait; wire [15:0] joystick_0, joystick_1, joystick_2, joystick_3; -wire [15:0] joystick_analog_0; +wire [15:0] joystick_analog_0, joystick_analog_1; wire [10:0] ps2_key; wire [7:0] filetype; @@ -291,14 +291,12 @@ wire [63:0] img_size; wire [32:0] RTC_time; -hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io +hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io ( .clk_sys(clk_sys), .HPS_BUS(HPS_BUS), .EXT_BUS(), - .conf_str(CONF_STR), - .ioctl_download(ioctl_download), .ioctl_wr(ioctl_wr), .ioctl_addr(ioctl_addr), @@ -306,13 +304,13 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io .ioctl_wait(ioctl_wait), .ioctl_index(filetype), - .sd_lba(sd_lba), + .sd_lba('{sd_lba}), .sd_rd(sd_rd), .sd_wr(sd_wr), .sd_ack(sd_ack), .sd_buff_addr(sd_buff_addr), .sd_buff_dout(sd_buff_dout), - .sd_buff_din(sd_buff_din), + .sd_buff_din('{sd_buff_din}), .sd_buff_wr(sd_buff_wr), .img_mounted(img_mounted), .img_readonly(img_readonly), @@ -331,7 +329,8 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io .joystick_1(joystick_1), .joystick_2(joystick_2), .joystick_3(joystick_3), - .joystick_analog_0(joystick_analog_0), + .joystick_l_analog_0(joystick_analog_0), + .joystick_l_analog_1(joystick_analog_1), .ps2_key(ps2_key), @@ -691,7 +690,7 @@ cart_top cart2 ( .rom_di ( rom2_do ), - .joystick_analog_0 ( joystick_analog_0 ), + .joystick_analog_0 ( joystick_analog_1 ), .RTC_time ( RTC_time ), .RTC_timestampOut ( ), diff --git a/sys/ascal.vhd b/sys/ascal.vhd index 2d21b35..f157e9f 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -383,8 +383,8 @@ ARCHITECTURE rtl OF ascal IS SIGNAL avl_fb_ena : std_logic; FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS - BEGIN - IF (freeze='1') THEN RETURN a; END IF; + BEGIN + IF (freeze='1') THEN RETURN a; END IF; IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; RETURN 1; @@ -401,7 +401,7 @@ ARCHITECTURE rtl OF ascal IS ---------------------------------------------------------- -- Output SIGNAL o_run : std_logic; - SIGNAL o_freeze : std_logic; + SIGNAL o_freeze : std_logic; SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); SIGNAL o_format : unsigned(5 DOWNTO 0); SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); @@ -1731,8 +1731,8 @@ BEGIN -------------------------------------------- -- Triple buffering. -- For intelaced video, half frames are updated independently - -- Input : Toggle buffer at end of input frame - o_freeze <= freeze; + -- Input : Toggle buffer at end of input frame + o_freeze <= freeze; o_inter <=i_inter; -- o_iendframe0<=i_endframe0; -- o_iendframe02<=o_iendframe0; @@ -1746,7 +1746,12 @@ BEGIN o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze); o_bufup1<='1'; END IF; + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); o_bufup1<='0'; @@ -1755,6 +1760,33 @@ BEGIN o_hdown<=i_hdown; -- o_vdown<=i_vdown; -- END IF; + + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; + + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; + -- Framebuffer mode. IF o_fb_ena='1' THEN o_ihsize<=o_fb_hsize; @@ -1774,25 +1806,6 @@ BEGIN o_stride<=to_unsigned(o_ihsize_temp2,14); o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); END IF; - - IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN - o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); - o_bufup0<='0'; - END IF; - - IF o_inter='0' THEN - o_ibuf1<=o_ibuf0; - o_obuf1<=o_obuf0; - END IF; - - -- Triple buffer disabled - IF o_mode(3)='0' THEN - o_obuf0<=0; - o_obuf1<=0; - o_ibuf0<=0; - o_ibuf1<=0; - END IF; - ------------------------------------------------------ o_hmode<=o_mode; IF o_hdown='1' AND DOWNSCALE THEN diff --git a/sys/hps_io.v b/sys/hps_io.sv similarity index 85% rename from sys/hps_io.v rename to sys/hps_io.sv index f784a8a..826b37c 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.sv @@ -24,15 +24,14 @@ // Use buffer to access SD card. It's time-critical part. // // WIDE=1 for 16 bit file I/O -// VDNUM 1-4 -module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) +// VDNUM 1..4 +// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384 +// +module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0) ( input clk_sys, inout [45:0] HPS_BUS, - // parameter STRLEN and the actual length of conf_str have to match - input [(8*STRLEN)-1:0] conf_str, - // buttons up to 32 output reg [31:0] joystick_0, output reg [31:0] joystick_1, @@ -42,12 +41,19 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output reg [31:0] joystick_5, // analog -127..+127, Y: [15:8], X: [7:0] - output reg [15:0] joystick_analog_0, - output reg [15:0] joystick_analog_1, - output reg [15:0] joystick_analog_2, - output reg [15:0] joystick_analog_3, - output reg [15:0] joystick_analog_4, - output reg [15:0] joystick_analog_5, + output reg [15:0] joystick_l_analog_0, + output reg [15:0] joystick_l_analog_1, + output reg [15:0] joystick_l_analog_2, + output reg [15:0] joystick_l_analog_3, + output reg [15:0] joystick_l_analog_4, + output reg [15:0] joystick_l_analog_5, + + output reg [15:0] joystick_r_analog_0, + output reg [15:0] joystick_r_analog_1, + output reg [15:0] joystick_r_analog_2, + output reg [15:0] joystick_r_analog_3, + output reg [15:0] joystick_r_analog_4, + output reg [15:0] joystick_r_analog_5, // paddle 0..255 output reg [7:0] paddle_0, @@ -86,7 +92,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted // SD block level access - input [31:0] sd_lba, + input [31:0] sd_lba[VDNUM], + input [5:0] sd_blk_cnt[VDNUM], // number of blocks-1, total size ((sd_blk_cnt+1)*(1<<(BLKSZ+7))) must be <= 16384! input [VD:0] sd_rd, input [VD:0] sd_wr, output reg [VD:0] sd_ack, @@ -94,9 +101,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) // SD byte level access. Signals for 2-PORT altsyncram. output reg [AW:0] sd_buff_addr, output reg [DW:0] sd_buff_dout, - input [DW:0] sd_buff_din, + input [DW:0] sd_buff_din[VDNUM], output reg sd_buff_wr, - input [15:0] sd_req_type, // ARM -> FPGA download output reg ioctl_download = 0, // signal indicating an active download @@ -105,6 +111,7 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) 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 ioctl_upload_req, input [DW:0] ioctl_din, output reg ioctl_rd, output reg [31:0] ioctl_file_ext, @@ -156,10 +163,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) assign EXT_BUS[31:16] = HPS_BUS[31:16]; assign EXT_BUS[35:33] = HPS_BUS[35:33]; -localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1; - localparam DW = (WIDE) ? 15 : 7; -localparam AW = (WIDE) ? 7 : 8; +localparam AW = (WIDE) ? 12 : 13; localparam VD = VDNUM-1; wire io_strobe= HPS_BUS[33]; @@ -182,22 +187,18 @@ assign forced_scandoubler = cfg[4]; //cfg[5] - ypbpr handled in sys_top assign direct_video = cfg[10]; -// command byte read by the io controller -wire [15:0] sd_cmd = -{ - 2'b00, - (VDNUM>=4) ? sd_wr[3] : 1'b0, - (VDNUM>=3) ? sd_wr[2] : 1'b0, - (VDNUM>=2) ? sd_wr[1] : 1'b0, +reg [3:0] sdn; +reg [3:0] sd_rrb = 0; +always_comb begin + int n, i; - (VDNUM>=4) ? sd_rd[3] : 1'b0, - (VDNUM>=3) ? sd_rd[2] : 1'b0, - (VDNUM>=2) ? sd_rd[1] : 1'b0, - - 4'h5, 1'b0, 1'b0, - sd_wr[0], - sd_rd[0] -}; + sdn = 0; + for(i = VDNUM - 1; i >= 0; i = i - 1) begin + n = i + sd_rrb; + if(n >= VDNUM) n = n - VDNUM; + if(sd_wr[n] | sd_rd[n]) sdn = n[3:0]; + end +end ///////////////////////////////////////////////////////// @@ -221,6 +222,19 @@ video_calc video_calc ///////////////////////////////////////////////////////// +localparam STRLEN = $size(CONF_STR)>>3; +localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1; + +wire [7:0] conf_byte; +generate + if(CONF_STR_BRAM) begin + confstr_rom #(CONF_STR, STRLEN) confstr_rom(.*, .conf_addr(byte_cnt - 1'd1)); + end + else begin + assign conf_byte = CONF_STR[{(STRLEN - byte_cnt),3'b000} +:8]; + end +endgenerate + assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value}; reg gamma_en; reg gamma_wr; @@ -232,7 +246,8 @@ wire pressed = (ps2_key_raw[15:8] != 8'hf0); wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0)); reg [MAX_W:0] byte_cnt; -wire [7:0] disk = 4'd1 << (io_din[10:8]-1'd1); +reg [3:0] sdn_ack; +wire [15:0] disk = 16'd1 << io_din[11:8]; always@(posedge clk_sys) begin : uio_block reg [15:0] cmd; @@ -243,16 +258,22 @@ always@(posedge clk_sys) begin : uio_block reg [3:0] stflg = 0; reg [63:0] status_req; reg old_status_set = 0; + reg old_upload_req = 0; + reg upload_req = 0; reg old_info = 0; reg [7:0] info_n = 0; reg [15:0] tmp1; reg [7:0] tmp2; + reg [3:0] sdn_r; old_status_set <= status_set; if(~old_status_set & status_set) begin stflg <= stflg + 1'd1; status_req <= status_in; end + + old_upload_req <= ioctl_upload_req; + if(~old_upload_req & ioctl_upload_req) upload_req <= 1; old_info <= info_req; if(~old_info & info_req) info_n <= info; @@ -291,14 +312,16 @@ always@(posedge clk_sys) begin : uio_block cmd <= io_din; casex(io_din) - 'hX17, - 'hX18: sd_ack <= VD ? disk[VD:0] : 1'd1; - 'h29: io_dout <= {4'hA, stflg}; - 'h2B: io_dout <= 1; - 'h2F: io_dout <= 1; - 'h32: io_dout <= gamma_bus[21]; - 'h36: begin io_dout <= info_n; info_n <= 0; end - 'h39: io_dout <= 1; + 'h16: begin io_dout <= {1'b1, sd_blk_cnt[sdn], BLKSZ[2:0], sdn, sd_wr[sdn], sd_rd[sdn]}; sdn_r <= sdn; end + 'h0X17, + 'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end + 'h29: io_dout <= {4'hA, stflg}; + 'h2B: io_dout <= 1; + 'h2F: io_dout <= 1; + 'h32: io_dout <= gamma_bus[21]; + 'h36: begin io_dout <= info_n; info_n <= 0; end + 'h39: io_dout <= 1; + 'h3C: if(upload_req) begin io_dout <= 1; upload_req <= 0; end endcase sd_buff_addr <= 0; @@ -347,42 +370,41 @@ always@(posedge clk_sys) begin : uio_block end // reading config string, returning a byte from string - 'h14: if(byte_cnt <= STRLEN) io_dout[7:0] <= conf_str[{(STRLEN - byte_cnt),3'b000} +:8]; + 'h14: if(byte_cnt <= STRLEN) io_dout[7:0] <= conf_byte; // reading sd card status - 'h16: if(!byte_cnt[MAX_W:3]) begin - case(byte_cnt[2:0]) - 1: io_dout <= sd_cmd; - 2: io_dout <= sd_lba[15:0]; - 3: io_dout <= sd_lba[31:16]; - 4: io_dout <= sd_req_type; + 'h16: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: sd_rrb <= (sd_rrb == VD) ? 4'd0 : (sd_rrb + 1'd1); + 2: io_dout <= sd_lba[sdn_r][15:0]; + 3: io_dout <= sd_lba[sdn_r][31:16]; endcase end // send sector IO -> FPGA // flag that download begins - 'hX17: begin + 'h0X17: begin sd_buff_dout <= io_din[DW:0]; b_wr <= 1; end // reading sd card write data - 'hX18: begin + 'h0X18: begin if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; - io_dout <= sd_buff_din; + io_dout <= sd_buff_din[sdn_ack]; end - // joystick analog + // joystick left analog 'h1a: if(!byte_cnt[MAX_W:2]) begin case(byte_cnt[1:0]) 1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index 2: case(stick_idx) - 0: joystick_analog_0 <= io_din; - 1: joystick_analog_1 <= io_din; - 2: joystick_analog_2 <= io_din; - 3: joystick_analog_3 <= io_din; - 4: joystick_analog_4 <= io_din; - 5: joystick_analog_5 <= io_din; + 0: joystick_l_analog_0 <= io_din; + 1: joystick_l_analog_1 <= io_din; + 2: joystick_l_analog_2 <= io_din; + 3: joystick_l_analog_3 <= io_din; + 4: joystick_l_analog_4 <= io_din; + 5: joystick_l_analog_5 <= io_din; 15: case(pdsp_idx) 0: paddle_0 <= io_din[7:0]; 1: paddle_1 <= io_din[7:0]; @@ -401,6 +423,21 @@ always@(posedge clk_sys) begin : uio_block endcase end + // joystick right analog + 'h3d: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: stick_idx <= io_din[3:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_r_analog_0 <= io_din; + 1: joystick_r_analog_1 <= io_din; + 2: joystick_r_analog_2 <= io_din; + 3: joystick_r_analog_3 <= io_din; + 4: joystick_r_analog_4 <= io_din; + 5: joystick_r_analog_5 <= io_din; + endcase + endcase + end + // notify image selection 'h1c: begin img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; @@ -925,3 +962,16 @@ always @(posedge clk_100) begin end endmodule + +module confstr_rom #(parameter CONF_STR, STRLEN) +( + input clk_sys, + input [$clog2(STRLEN+1)-1:0] conf_addr, + output reg [7:0] conf_byte +); + +wire [7:0] rom[STRLEN]; +initial for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8]; +always @ (posedge clk_sys) conf_byte <= rom[conf_addr]; + +endmodule diff --git a/sys/sys.qip b/sys/sys.qip index 26f8474..2854eaf 100644 --- a/sys/sys.qip +++ b/sys/sys.qip @@ -30,4 +30,4 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f 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 ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hps_io.sv ] diff --git a/sys/sys_top.v b/sys/sys_top.v index 3b9179a..dbf8a8a 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -292,7 +292,8 @@ reg cfg_custom_t = 0; reg [5:0] cfg_custom_p1; reg [31:0] cfg_custom_p2; -reg [4:0] vol_att = 0; +reg [4:0] vol_att; +initial vol_att = 5'b11111; reg [6:0] coef_addr; reg [8:0] coef_data;