- added 2x resolution mode

- updated framework
- improved ddr3 access latency
- 30Hz flickereduce option
This commit is contained in:
Robert Peip
2020-06-17 15:33:34 +02:00
parent a05a8c0b13
commit cbeb6da8cc
24 changed files with 2419 additions and 906 deletions

View File

@@ -13,7 +13,7 @@ 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 Standard Edition"
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.0 Lite Edition"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
@@ -49,7 +49,8 @@ set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION
set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON
set_global_assignment -name ALM_REGISTER_PACKING_EFFORT LOW
set_global_assignment -name PLACEMENT_EFFORT_MULTIPLIER 1.0
set_global_assignment -name SEED 2
set_global_assignment -name SEED 3
set_global_assignment -name VERILOG_MACRO "USE_FB=1"
source sys/sys.tcl
source sys/sys_analog.tcl

109
GBA.sv
View File

@@ -65,6 +65,7 @@ module emu
// 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
@@ -121,7 +122,22 @@ module emu
input [6:0] USER_IN,
output [6:0] USER_OUT,
input OSD_STATUS
input OSD_STATUS,
// Use framebuffer from 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)
//
// stride is modulo 256 of bytes
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
input FB_VBL,
input FB_LL
);
assign ADC_BUS = 'Z;
@@ -141,6 +157,12 @@ assign VIDEO_ARY = status[1] ? 8'd9 : 8'd2;
assign {SD_SCK, SD_MOSI, SD_CS} = 'Z;
assign FB_EN = status[21] || status[22];
assign FB_FORMAT = 5'b00110;
assign FB_WIDTH = 12'd480;
assign FB_HEIGHT = 12'd320;
/////////////////////// CLOCK/RESET ///////////////////////////////////
wire pll_locked;
@@ -163,7 +185,7 @@ wire reset = RESET | buttons[1] | status[0] | cart_download | bk_loading | hold_
// 0 1 2 3 4 5 6
// 0123456789012345678901234567890123456789012345678901234567890123
// 0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV
// XXXXXXXXX XXXXXXXXXXXXXXXXXXXXX
// XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX
`include "build_id.v"
parameter CONF_STR = {
@@ -183,8 +205,9 @@ parameter CONF_STR = {
"O1,Aspect Ratio,3:2,16:9;",
"O24,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;",
"OOQ,Modify Colors,Off,GBA 2.2,GBA 1.6,NDS 1.6,VBA 1.4,75%,50%,25%;",
"OJ,Flickerblend,Off,On;",
"O9A,Flickerblend,Off,Blend,30Hz;",
"OK,Spritelimit,Off,On;",
"OLM,2XResolution,Off,Background,Sprites,Both;",
"O78,Stereo Mix,None,25%,50%,100%;",
"-;",
"OEF,Storage,Auto,SDRAM,DDR3;",
@@ -445,8 +468,10 @@ gba
.memory_remap(memory_remap_quirk),
.save_state(ss_save),
.load_state(ss_load),
.interframe_blend(status[19]),
.interframe_blend(status[10:9]),
.maxpixels(status[20]),
.hdmode2x_bg(status[21]),
.hdmode2x_obj(status[22]),
.shade_mode(shadercolors),
.specialmodule(gpio_quirk),
.solar_in(status[31:29]),
@@ -516,6 +541,14 @@ gba
.pixel_out_data(pixel_data), // RGB data for framebuffer
.pixel_out_we(pixel_we), // new pixel for framebuffer
.largeimg_out_base(FB_BASE),
.largeimg_out_addr(fb_addr),
.largeimg_out_data(fb_din),
.largeimg_out_req(fb_req),
.largeimg_out_done(fb_ack),
.largeimg_newframe(FB_VBL),
.largeimg_singlebuf(FB_LL),
.sound_out_left(AUDIO_L),
.sound_out_right(AUDIO_R)
);
@@ -633,6 +666,11 @@ wire [31:0] sdr_sdram_dout1, sdr_sdram_dout2, sdr_bus_dout;
wire [15:0] sdr_bram_din;
wire sdr_sdram_ack, sdr_bus_ack, sdr_bram_ack;
wire [27:2] fb_addr;
wire [63:0] fb_din;
wire fb_req;
wire fb_ack;
sdram sdram
(
.*,
@@ -708,7 +746,13 @@ ddram ddram
.ch4_dout(ss_dout),
.ch4_req(ss_req),
.ch4_rnw(ss_rnw),
.ch4_ready(ss_ack)
.ch4_ready(ss_ack),
.ch5_addr({fb_addr, 1'b0}),
.ch5_din(fb_din),
.ch5_req(fb_req),
.ch5_ready(fb_ack)
);
wire [127:0] time_din_h = {32'd0, time_din, "RT"};
@@ -718,20 +762,51 @@ wire bram_ack = sdram_en ? sdr_bram_ack : ddr_bram_ack;
assign sd_buff_din = extra_data_addr ? (time_din_h[{sd_buff_addr[2:0], 4'b0000} +: 16]) : bram_buff_out;
wire [15:0] bram_buff_out;
SyncRamDual #(16,8) bram
altsyncram altsyncram_component
(
.clk(clk_sys),
.addr_a(bram_addr),
.we_a(~bk_loading & bram_ack),
.datain_a(bram_din),
.dataout_a(bram_dout),
.addr_b(sd_buff_addr),
.we_b(sd_buff_wr && ~extra_data_addr),
.datain_b(sd_buff_dout),
.dataout_b(bram_buff_out)
.address_a (bram_addr),
.address_b (sd_buff_addr),
.clock0 (clk_sys),
.clock1 (clk_sys),
.data_a (bram_din),
.data_b (sd_buff_dout),
.wren_a (~bk_loading & bram_ack),
.wren_b (sd_buff_wr && ~extra_data_addr),
.q_a (bram_dout),
.q_b (bram_buff_out),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.rden_a (1'b1),
.rden_b (1'b1)
);
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.intended_device_family = "Cyclone V",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 256,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 8,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 16,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";
reg [7:0] bram_addr;
reg bram_tx_start;

View File

@@ -31,7 +31,7 @@ As the BIOS is already replaced at boot time, you must save this settings and ha
- Savestates
- FastForward - speed up game by factor 2-4
- CPU Turbomode - give games additional CPU power
- Flickerblend - turn on for games like F-Zero, Mario Kart or NES Classics to prevent flickering effects
- Flickerblend - set to blend or 30Hz mode for games like F-Zero, Mario Kart or NES Classics to prevent flickering effects
- Spritelimit - turn on to prevent wrong sprites for games that rely on the limit (opt-in)
- Cheats
- Color optimizations: shader colors and desaturate
@@ -40,6 +40,7 @@ As the BIOS is already replaced at boot time, you must save this settings and ha
- Solar Sensor: Set brightness in OSD
- Gyro: use analog stick (map stick in Mister Main before)
- RTC: automatically used, works with RTC board or internet connection
- 2x Resolution: game is rendered at 480x320 instead of 240x160 pixels
# Savestates
Core provides 4 slots to save the state. The first slot gets saved to disk and automatically loaded (but not applied)
@@ -62,6 +63,14 @@ Currently there are only few games known that produce glitches without sprite pi
- Gunstar Super Heroes
- Famicon Mini Series Vol21 - Vol30
# 2x Resolution
Improved rendering resolution for:
- Affine background: "Mode7" games, typically racing games like Mario Kart
- Affine sprites: games that scale or rotate sprites
This rendering is experimental and can cause glitches, as not all game behavior can be supported.
Those glitches can not be fixed without gamespecific hacks and therefore will not be fixed.
Please don't add bugs in such cases.
# Cartridge Hardware supported games
- RTC: Pokemon Sapphire+Ruby+Emerald, Boktai 1+2+3, Sennen Kazoku, Rockman EXE 4.5
- Solar Sensor: Boktai 1+2+3

View File

@@ -60,7 +60,13 @@ module ddram
input [63:0] ch4_din,
input ch4_req,
input ch4_rnw,
output ch4_ready
output ch4_ready,
// framebuffer
input [27:1] ch5_addr,
input [63:0] ch5_din,
input ch5_req,
output ch5_ready
);
reg [7:0] ram_burst;
@@ -71,7 +77,7 @@ reg ram_read = 0;
reg ram_write = 0;
reg [7:0] ram_be;
reg [4:1] ready;
reg [5:1] ready;
assign DDRAM_BURSTCNT = ram_burst;
assign DDRAM_BE = ram_read ? 8'hFF : ram_be;
@@ -88,18 +94,19 @@ assign ch1_ready = ready[1];
assign ch2_ready = ready[2];
assign ch3_ready = ready[3];
assign ch4_ready = ready[4];
assign ch5_ready = ready[5];
reg [63:0] next_q[2:1];
reg [27:1] cache_addr[2:1];
reg [1:0] state = 0;
reg [2:1] cached = 0;
reg [2:0] ch = 0;
reg [4:1] ch_rq;
reg [5:1] ch_rq;
always @(posedge DDRAM_CLK) begin
ch_rq <= ch_rq | {ch4_req, ch3_req, ch2_req, ch1_req};
ch_rq <= ch_rq | {ch5_req, ch4_req, ch3_req, ch2_req, ch1_req};
ready <= 0;
if(!DDRAM_BUSY) begin
@@ -107,7 +114,7 @@ always @(posedge DDRAM_CLK) begin
ram_read <= 0;
case(state)
0: if(ch_rq[1]) begin
0: if(ch_rq[1] || ch1_req) begin
ch_rq[1] <= 0;
ch <= 1;
ram_data <= {4{ch1_din}};
@@ -141,7 +148,7 @@ always @(posedge DDRAM_CLK) begin
state <= 1;
end
end
else if(ch_rq[2]) begin
else if(ch_rq[2] || ch2_req) begin
ch_rq[2] <= 0;
ch <= 2;
ram_data <= {2{ch2_din}};
@@ -175,7 +182,7 @@ always @(posedge DDRAM_CLK) begin
state <= 1;
end
end
else if(ch_rq[3]) begin
else if(ch_rq[3] || ch3_req) begin
ch_rq[3] <= 0;
ch <= 3;
ram_address <= {ch3_addr, 2'b00};
@@ -192,7 +199,7 @@ always @(posedge DDRAM_CLK) begin
state <= 1;
end
end
else if(ch_rq[4]) begin
else if(ch_rq[4] || ch4_req) begin
ch_rq[4] <= 0;
ch <= 4;
ram_data <= ch4_din;
@@ -207,6 +214,16 @@ always @(posedge DDRAM_CLK) begin
ram_read <= 1;
state <= 1;
end
end
else if(ch_rq[5] || ch5_req) begin
ch_rq[5] <= 0;
ch <= 5;
ram_data <= ch5_din;
ram_be <= 8'hFF;
ram_address <= ch5_addr;
ram_write <= 1;
ram_burst <= 1;
ready[5] <= 1;
end
1: if(DDRAM_DOUT_READY) begin

View File

@@ -7,6 +7,7 @@ set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_dma_mo
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_merge.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode0.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode2.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode2_2x.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_mode345.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_drawer_obj.vhd ]
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) gba_gpu.vhd ]

View File

@@ -3,6 +3,12 @@ use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity gba_drawer_mode2 is
generic
(
DXYBITS : integer := 16;
ACCURACYBITS : integer := 28;
PIXELCOUNT : integer := 240
);
port
(
clk100 : in std_logic;
@@ -17,16 +23,16 @@ entity gba_drawer_mode2 is
wrapping : in std_logic;
mosaic : in std_logic;
Mosaic_H_Size : in unsigned(3 downto 0);
refX : in signed(27 downto 0);
refY : in signed(27 downto 0);
refX : in signed;
refY : in signed;
refX_mosaic : in signed(27 downto 0);
refY_mosaic : in signed(27 downto 0);
dx : in signed(15 downto 0);
dy : in signed(15 downto 0);
dx : in signed(DXYBITS - 1 downto 0);
dy : in signed(DXYBITS - 1 downto 0);
pixel_we : out std_logic := '0';
pixeldata : buffer std_logic_vector(15 downto 0) := (others => '0');
pixel_x : out integer range 0 to 239;
pixel_x : out integer range 0 to (PIXELCOUNT - 1);
PALETTE_Drawer_addr : out integer range 0 to 127;
PALETTE_Drawer_data : in std_logic_vector(31 downto 0);
@@ -72,14 +78,14 @@ architecture arch of gba_drawer_mode2 is
signal mapbaseaddr : integer;
signal tilebaseaddr : integer;
signal realX : signed(27 downto 0);
signal realY : signed(27 downto 0);
signal realX : signed(ACCURACYBITS - 1 downto 0);
signal realY : signed(ACCURACYBITS - 1 downto 0);
signal xxx : signed(19 downto 0);
signal yyy : signed(19 downto 0);
signal xxx_pre : signed(19 downto 0);
signal yyy_pre : signed(19 downto 0);
signal x_cnt : integer range 0 to 239;
signal x_cnt : integer range 0 to (PIXELCOUNT - 1);
signal scroll_mod : integer range 128 to 1024;
signal tileinfo : std_logic_vector(7 downto 0) := (others => '0');
@@ -98,8 +104,8 @@ begin
VRAM_Drawer_addr <= to_integer(VRAM_byteaddr(15 downto 2));
PALETTE_Drawer_addr <= to_integer(unsigned(PALETTE_byteaddr(8 downto 2)));
xxx_pre <= realX(27 downto 8);
yyy_pre <= realY(27 downto 8);
xxx_pre <= realX(realX'left downto realX'left - 19);
yyy_pre <= realY(realY'left downto realY'left - 19);
-- vramfetch
process (clk100)
@@ -112,12 +118,14 @@ begin
when IDLE =>
if (line_trigger = '1') then
if (mosaic = '1') then
realX <= refX_mosaic;
realY <= refY_mosaic;
realX <= (others => '0');
realY <= (others => '0');
if (mosaic = '1' and unsigned(Mosaic_H_Size) > 0) then
realX(realX'left downto realX'left - refX_mosaic'length + 1) <= refX_mosaic;
realY(realY'left downto realY'left - refY_mosaic'length + 1) <= refY_mosaic;
else
realX <= refX;
realY <= refY;
realX(realX'left downto realX'left - refX'length + 1) <= refX;
realY(realY'left downto realY'left - refY'length + 1) <= refY;
end if;
elsif (drawline = '1') then
busy <= '1';
@@ -150,7 +158,7 @@ begin
xxx <= xxx_pre;
yyy <= yyy_pre;
if (xxx_pre < 0 or yyy_pre < 0 or xxx_pre >= scroll_mod or yyy_pre >= scroll_mod) then
if (x_cnt < 239) then
if (x_cnt < (PIXELCOUNT - 1)) then
vramfetch <= CALCADDR1;
x_cnt <= x_cnt + 1;
else
@@ -234,7 +242,7 @@ begin
when FETCHDONE =>
if (palettefetch = IDLE) then
if (x_cnt < 239) then
if (x_cnt < (PIXELCOUNT - 1)) then
vramfetch <= CALCADDR1;
x_cnt <= x_cnt + 1;
else

View File

@@ -3,6 +3,12 @@ use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity gba_drawer_obj is
generic
(
RESMULT : integer := 1;
PIXELCOUNT : integer := 240;
YMULTOFFSET : integer := 0
);
port
(
clk100 : in std_logic;
@@ -26,7 +32,7 @@ entity gba_drawer_obj is
pixeldata_color : out std_logic_vector(15 downto 0) := (others => '0');
pixel_we_settings : out std_logic := '0';
pixeldata_settings : out std_logic_vector(2 downto 0) := (others => '0');
pixel_x : out integer range 0 to 239;
pixel_x : out integer range 0 to (PIXELCOUNT - 1);
pixel_objwnd : out std_logic := '0';
OAMRAM_Drawer_addr : buffer integer range 0 to 255;
@@ -43,6 +49,8 @@ end entity;
architecture arch of gba_drawer_obj is
constant RESMULTACCDIV : integer := 256 * RESMULT;
-- Atr0
constant OAM_Y_HI : integer := 7;
constant OAM_Y_LO : integer := 0;
@@ -158,13 +166,16 @@ architecture arch of gba_drawer_obj is
signal x : integer range 0 to 255;
signal realX : integer range -8388608 to 8388607;
signal realY : integer range -8388608 to 8388607;
signal target : integer range 0 to 239;
signal target : integer range 0 to (PIXELCOUNT - 1);
signal second_pix : std_logic;
signal skippixel : std_logic;
signal issue_pixel : std_logic;
signal pixeladdr_x : unsigned(14 downto 0) := (others => '0');
signal pixeladdr_x_noaff : unsigned(14 downto 0);
signal rescounter : integer range 0 to RESMULT - 1;
signal rescounter_current: integer range 0 to RESMULT - 1;
signal pixeladdr_x_aff0 : unsigned(14 downto 0);
signal pixeladdr_x_aff1 : unsigned(14 downto 0);
signal pixeladdr_x_aff2 : unsigned(14 downto 0);
@@ -182,17 +193,17 @@ architecture arch of gba_drawer_obj is
objwnd : std_logic;
end record;
type t_pixelarray is array(0 to 239) of tpixel;
type t_pixelarray is array(0 to (PIXELCOUNT - 1)) of tpixel;
signal pixelarray : t_pixelarray;
signal Pixel_wait : tpixel;
signal Pixel_readback : tpixel;
signal Pixel_merge : tpixel;
signal target_start : integer range 0 to 239;
signal target_eval : integer range 0 to 239;
signal target_wait : integer range 0 to 239;
signal target_merge : integer range 0 to 239;
signal target_start : integer range 0 to (PIXELCOUNT - 1);
signal target_eval : integer range 0 to (PIXELCOUNT - 1);
signal target_wait : integer range 0 to (PIXELCOUNT - 1);
signal target_merge : integer range 0 to (PIXELCOUNT - 1);
signal enable_start : std_logic;
signal enable_eval : std_logic;
@@ -367,6 +378,7 @@ begin
case (PIXELGen) is
when WAITOAM =>
rescounter <= 0;
if (OAMFetch = DONE) then
PIXELGen <= CALCMOSAIC;
Pixel_data0 <= OAM_data0;
@@ -505,8 +517,12 @@ begin
end if;
-- affine
realX <= pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3;
realY <= pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7;
realX <= (pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3) * resmult;
realY <= (pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7) * resmult;
if (YMULTOFFSET = 1) then
realX <= ((pixeladdr_pre_a0 - pixeladdr_pre_a1 - pixeladdr_pre_a2 + pixeladdr_pre_a3) * resmult) + dmx;
realY <= ((pixeladdr_pre_a4 - pixeladdr_pre_a5 - pixeladdr_pre_a6 + pixeladdr_pre_a7) * resmult) + dmy;
end if;
-- non affine
if (Pixel_data1(OAM_VFLIP) = '1') then
@@ -529,7 +545,13 @@ begin
elsif (x >= fieldX) then
PIXELGen <= WAITOAM;
else
x <= x + 1;
rescounter_current <= rescounter;
if (rescounter = RESMULT - 1) then
x <= x + 1;
rescounter <= 0;
else
rescounter <= rescounter + 1;
end if;
if (x + posX > 239) then -- end of line already reached
PIXELGen <= WAITOAM;
else
@@ -552,16 +574,16 @@ begin
end if;
if (Pixel_data0(OAM_AFFINE) = '1') then
if (realX < 0 or (realX / 256) >= sizeX or realY < 0 or (realY / 256) >= sizeY) then
if (realX < 0 or (realX / RESMULTACCDIV) >= sizeX or realY < 0 or (realY / RESMULTACCDIV) >= sizeY) then
skippixel <= '1';
end if;
-- synthesis translate_off
if (realX >= 0 and (realX / 256) < sizeX and realY >= 0 and (realY / 256) < sizeY) then
if (realX >= 0 and (realX / RESMULTACCDIV) < sizeX and realY >= 0 and (realY / RESMULTACCDIV) < sizeY) then
-- synthesis translate_on
xxx := realX / 256;
yyy := realY / 256;
xxx := realX / RESMULTACCDIV;
yyy := realY / RESMULTACCDIV;
if (xxx mod 2 = 1) then second_pix <= '1'; else second_pix <= '0'; end if;
pixeladdr_x_aff0 <= to_unsigned(((yyy mod 8) * x_size), 15);
@@ -650,7 +672,7 @@ begin
-- zero cycle - address for vram is written in this cycle
enable_start <= issue_pixel;
target_start <= target;
target_start <= (target * RESMULT) + rescounter_current;
readaddr_mux <= pixeladdr_x(1 downto 0);
second_pix_start <= second_pix;

View File

@@ -23,17 +23,24 @@ entity gba_gpu is
gb_bus : inout proc_bus_gb_type := ((others => 'Z'), (others => 'Z'), (others => 'Z'), 'Z', 'Z', 'Z', "ZZ", "ZZZZ", 'Z');
lockspeed : in std_logic;
interframe_blend : in std_logic;
interframe_blend : in std_logic_vector(1 downto 0);
maxpixels : in std_logic;
shade_mode : in std_logic_vector(2 downto 0);
hdmode2x_bg : in std_logic;
hdmode2x_obj : in std_logic;
bitmapdrawmode : out std_logic;
pixel_out_x : out integer range 0 to 239;
pixel_out_2x : out integer range 0 to 479;
pixel_out_y : out integer range 0 to 159;
pixel_out_addr : out integer range 0 to 38399;
pixel_out_data : out std_logic_vector(17 downto 0);
pixel_out_we : out std_logic := '0';
pixel2_out_x : out integer range 0 to 479;
pixel2_out_data : out std_logic_vector(17 downto 0);
pixel2_out_we : out std_logic := '0';
new_cycles : in unsigned(7 downto 0);
new_cycles_valid : in std_logic;
@@ -86,11 +93,15 @@ architecture arch of gba_gpu is
signal pixelpos : integer range 0 to 511;
signal pixel_x : integer range 0 to 239;
signal pixel_2x : integer range 0 to 479;
signal pixel_y : integer range 0 to 159;
signal pixel_addr : integer range 0 to 38399;
signal pixel_data : std_logic_vector(14 downto 0);
signal pixel_we : std_logic := '0';
signal pixel2_2x : integer range 0 to 479;
signal pixel2_data : std_logic_vector(14 downto 0);
signal pixel2_we : std_logic := '0';
signal vram_block_mode : std_logic;
begin
@@ -147,15 +158,22 @@ begin
lockspeed => lockspeed,
interframe_blend => interframe_blend,
maxpixels => maxpixels,
hdmode2x_bg => hdmode2x_bg ,
hdmode2x_obj => hdmode2x_obj,
bitmapdrawmode => bitmapdrawmode,
vram_block_mode => vram_block_mode,
pixel_out_x => pixel_x,
pixel_out_x => pixel_x,
pixel_out_2x => pixel_2x,
pixel_out_y => pixel_y,
pixel_out_addr => pixel_addr,
pixel_out_data => pixel_data,
pixel_out_we => pixel_we,
pixel2_out_x => pixel2_2x,
pixel2_out_data => pixel2_data,
pixel2_out_we => pixel2_we,
linecounter => linecounter_drawer,
drawline => drawline,
@@ -190,8 +208,8 @@ begin
PALETTE_OAM_datain => PALETTE_OAM_datain,
PALETTE_OAM_dataout => PALETTE_OAM_dataout,
PALETTE_OAM_we => PALETTE_OAM_we
);
);
igba_gpu_colorshade : entity work.gba_gpu_colorshade
port map
(
@@ -200,16 +218,40 @@ begin
shade_mode => shade_mode,
pixel_in_x => pixel_x,
pixel_in_2x => pixel_2x,
pixel_in_y => pixel_y,
pixel_in_addr => pixel_addr,
pixel_in_data => pixel_data,
pixel_in_we => pixel_we,
pixel_out_x => pixel_out_x,
pixel_out_2x => pixel_out_2x,
pixel_out_y => pixel_out_y,
pixel_out_addr => pixel_out_addr,
pixel_out_data => pixel_out_data,
pixel_out_we => pixel_out_we
);
igba_gpu_colorshade2 : entity work.gba_gpu_colorshade
port map
(
clk100 => clk100,
shade_mode => shade_mode,
pixel_in_x => 0,
pixel_in_2x => pixel2_2x,
pixel_in_y => 0,
pixel_in_addr => 0,
pixel_in_data => pixel2_data,
pixel_in_we => pixel2_we,
pixel_out_x => open,
pixel_out_2x => pixel2_out_x,
pixel_out_y => open,
pixel_out_addr => open,
pixel_out_data => pixel2_out_data,
pixel_out_we => pixel2_out_we
);
end architecture;

View File

@@ -10,12 +10,14 @@ entity gba_gpu_colorshade is
shade_mode : in std_logic_vector(2 downto 0); -- 0 = off, 1..4 modes
pixel_in_x : in integer range 0 to 239;
pixel_in_2x : in integer range 0 to 479;
pixel_in_y : in integer range 0 to 159;
pixel_in_addr : in integer range 0 to 38399;
pixel_in_data : in std_logic_vector(14 downto 0);
pixel_in_we : in std_logic := '0';
pixel_out_x : out integer range 0 to 239;
pixel_out_2x : out integer range 0 to 479;
pixel_out_y : out integer range 0 to 159;
pixel_out_addr : out integer range 0 to 38399;
pixel_out_data : out std_logic_vector(17 downto 0);
@@ -156,6 +158,7 @@ architecture arch of gba_gpu_colorshade is
-- shade processing
signal pixel_1_x : integer range 0 to 239;
signal pixel_1_2x : integer range 0 to 479;
signal pixel_1_y : integer range 0 to 159;
signal pixel_1_addr : integer range 0 to 38399;
signal pixel_1_data : std_logic_vector(14 downto 0);
@@ -165,6 +168,7 @@ architecture arch of gba_gpu_colorshade is
signal color_linear_3 : integer range 0 to 1023;
signal pixel_2_x : integer range 0 to 239;
signal pixel_2_2x : integer range 0 to 479;
signal pixel_2_y : integer range 0 to 159;
signal pixel_2_addr : integer range 0 to 38399;
signal pixel_2_we : std_logic := '0';
@@ -172,6 +176,7 @@ architecture arch of gba_gpu_colorshade is
signal shade_precalc : t_shade_precalc := (others => (others => 0));
signal pixel_3_x : integer range 0 to 239;
signal pixel_3_2x : integer range 0 to 479;
signal pixel_3_y : integer range 0 to 159;
signal pixel_3_addr : integer range 0 to 38399;
signal pixel_3_we : std_logic := '0';
@@ -179,6 +184,7 @@ architecture arch of gba_gpu_colorshade is
signal shade_linear : t_shade_linear;
signal pixel_4_x : integer range 0 to 239;
signal pixel_4_2x : integer range 0 to 479;
signal pixel_4_y : integer range 0 to 159;
signal pixel_4_addr : integer range 0 to 38399;
signal pixel_4_we : std_logic := '0';
@@ -186,6 +192,7 @@ architecture arch of gba_gpu_colorshade is
signal clip_linear : t_clip_linear;
signal pixel_5_x : integer range 0 to 239;
signal pixel_5_2x : integer range 0 to 479;
signal pixel_5_y : integer range 0 to 159;
signal pixel_5_addr : integer range 0 to 38399;
signal pixel_5_we : std_logic := '0';
@@ -262,6 +269,7 @@ begin
-- clock 1 - lookup linear color
pixel_1_x <= pixel_in_x;
pixel_1_2x <= pixel_in_2x;
pixel_1_y <= pixel_in_y;
pixel_1_addr <= pixel_in_addr;
pixel_1_we <= pixel_in_we;
@@ -273,6 +281,7 @@ begin
-- clock 2 - precalc shades
pixel_2_x <= pixel_1_x;
pixel_2_2x <= pixel_1_2x;
pixel_2_y <= pixel_1_y;
pixel_2_addr <= pixel_1_addr;
pixel_2_we <= pixel_1_we;
@@ -303,6 +312,7 @@ begin
-- clock 3 - apply shading
pixel_3_x <= pixel_2_x;
pixel_3_2x <= pixel_2_2x;
pixel_3_y <= pixel_2_y;
pixel_3_addr <= pixel_2_addr;
pixel_3_we <= pixel_2_we;
@@ -313,6 +323,7 @@ begin
-- clock 4 - clip
pixel_4_x <= pixel_3_x;
pixel_4_2x <= pixel_3_2x;
pixel_4_y <= pixel_3_y;
pixel_4_addr <= pixel_3_addr;
pixel_4_we <= pixel_3_we;
@@ -329,6 +340,7 @@ begin
-- clock 5 - lookup upper 3 bits of color
pixel_5_x <= pixel_4_x;
pixel_5_2x <= pixel_4_2x;
pixel_5_y <= pixel_4_y;
pixel_5_addr <= pixel_4_addr;
pixel_5_we <= pixel_4_we;
@@ -355,6 +367,7 @@ begin
-- clock 6 - lookup lower 3 bits of color
pixel_out_x <= pixel_5_x;
pixel_out_2x <= pixel_5_2x;
pixel_out_y <= pixel_5_y;
pixel_out_addr <= pixel_5_addr;
pixel_out_we <= pixel_5_we;
@@ -372,6 +385,7 @@ begin
else
pixel_out_x <= pixel_in_x;
pixel_out_2x <= pixel_in_2x;
pixel_out_y <= pixel_in_y;
pixel_out_addr <= pixel_in_addr;
pixel_out_we <= pixel_in_we;

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,8 @@ library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library MEM;
use work.pProc_bus_gba.all;
use work.pReg_savestates.all;
@@ -33,9 +35,11 @@ entity gba_top is
memory_remap : in std_logic;
save_state : in std_logic;
load_state : in std_logic;
interframe_blend : in std_logic;
interframe_blend : in std_logic_vector(1 downto 0); -- 0 = off, 1 = blend, 2 = 30hz
maxpixels : in std_logic; -- limit pixels per line
shade_mode : in std_logic_vector(2 downto 0); -- 0 = off, 1..4 modes
hdmode2x_bg : in std_logic;
hdmode2x_obj : in std_logic;
specialmodule : in std_logic; -- 0 = off, 1 = use gamepak GPIO Port at address 0x080000C4..0x080000C8
solar_in : in std_logic_vector(2 downto 0);
tilt : in std_logic; -- 0 = off, 1 = use tilt at address 0x0E008200, 0x0E008300, 0x0E008400, 0x0E008500
@@ -108,20 +112,28 @@ entity gba_top is
GBA_BusReadData : out std_logic_vector(31 downto 0);
GBA_Bus_written : in std_logic;
-- display data
pixel_out_x : out integer range 0 to 239;
pixel_out_y : out integer range 0 to 159;
pixel_out_addr : out integer range 0 to 38399; -- address for framebuffer
pixel_out_data : out std_logic_vector(17 downto 0); -- RGB data for framebuffer
pixel_out_we : out std_logic; -- new pixel for framebuffer
-- sound
sound_out_left : out std_logic_vector(15 downto 0) := (others => '0');
sound_out_right : out std_logic_vector(15 downto 0) := (others => '0');
-- debug
debug_cpu_pc : out std_logic_vector(31 downto 0);
debug_cpu_mixed : out std_logic_vector(31 downto 0);
debug_irq : out std_logic_vector(31 downto 0);
debug_dma : out std_logic_vector(31 downto 0);
debug_mem : out std_logic_vector(31 downto 0)
pixel_out_x : buffer integer range 0 to 239;
pixel_out_y : buffer integer range 0 to 159;
pixel_out_addr : buffer integer range 0 to 38399; -- address for framebuffer
pixel_out_data : buffer std_logic_vector(17 downto 0); -- RGB data for framebuffer
pixel_out_we : buffer std_logic; -- new pixel for framebuffer
largeimg_out_base : out std_logic_vector(31 downto 0) := x"38000000";
largeimg_out_addr : buffer std_logic_vector(25 downto 0) := (others => '0');
largeimg_out_data : out std_logic_vector(63 downto 0);
largeimg_out_req : out std_logic := '0';
largeimg_out_done : in std_logic;
largeimg_newframe : in std_logic;
largeimg_singlebuf : in std_logic;
-- sound
sound_out_left : out std_logic_vector(15 downto 0) := (others => '0');
sound_out_right : out std_logic_vector(15 downto 0) := (others => '0');
-- debug
debug_cpu_pc : out std_logic_vector(31 downto 0);
debug_cpu_mixed : out std_logic_vector(31 downto 0);
debug_irq : out std_logic_vector(31 downto 0);
debug_dma : out std_logic_vector(31 downto 0);
debug_mem : out std_logic_vector(31 downto 0)
);
end entity;
@@ -322,6 +334,43 @@ architecture arch of gba_top is
signal CyclesVsync : unsigned(31 downto 0) := (others => '0');
signal bench_slow : integer range 0 to 1685375 := 0;
-- large image out
signal pixel_out_2x : integer range 0 to 479;
signal pixel_out_data2x : std_logic_vector(17 downto 0);
signal pixel_out_we2x : std_logic := '0';
signal pixel2_out_x : integer range 0 to 479;
signal pixel2_out_data : std_logic_vector(17 downto 0);
signal pixel2_out_we : std_logic;
signal pixel_write_addr : integer range 0 to 239;
signal pixel_write_data : std_logic_vector(35 downto 0);
signal pixel_write_ena : std_logic := '0';
signal pixel2_write_addr : integer range 0 to 239;
signal pixel2_write_data : std_logic_vector(35 downto 0);
signal pixel2_write_ena : std_logic := '0';
type tstate is
(
IDLE,
READPIXEL,
WRITEPIXEL
);
signal state : tstate := IDLE;
signal pixel_out_y_1 : integer range 0 to 159 := 0;
signal pixelpos : integer range 0 to 240 := 0;
signal pixelpos2 : integer range 0 to 240 := 0;
signal pixelcnt : integer range 0 to 3 := 0;
signal firstpixel : std_logic := '0';
signal linebuffer_data : std_logic_vector(35 downto 0);
signal linebuffer2_data : std_logic_vector(35 downto 0);
signal pixeladdress : integer range 0 to 262143;
signal newframe_sreg : std_logic_vector(2 downto 0) := (others => '0');
signal current_frame : integer range 0 to 2 := 0;
signal frameoffset : integer range 0 to 2 := 0;
begin
-- dummy modules
@@ -770,14 +819,21 @@ begin
interframe_blend => interframe_blend,
maxpixels => maxpixels,
shade_mode => shade_mode,
hdmode2x_bg => hdmode2x_bg,
hdmode2x_obj => hdmode2x_obj,
bitmapdrawmode => bitmapdrawmode,
pixel_out_x => pixel_out_x,
pixel_out_2x => pixel_out_2x,
pixel_out_y => pixel_out_y,
pixel_out_addr => pixel_out_addr,
pixel_out_data => pixel_out_data,
pixel_out_we => pixel_out_we,
pixel2_out_x => pixel2_out_x,
pixel2_out_data => pixel2_out_data,
pixel2_out_we => pixel2_out_we,
new_cycles => new_cycles,
new_cycles_valid => new_cycles_valid,
@@ -1030,6 +1086,158 @@ begin
end if;
end process;
-- large pixel out
process (clk100)
begin
if rising_edge(clk100) then
pixel_write_ena <= '0';
if (pixel_out_we = '1') then
pixel_write_addr <= pixel_out_2x / 2;
if (pixel_out_2x mod 2 = 0) then
pixel_write_data(17 downto 0) <= pixel_out_data;
else
pixel_write_data(35 downto 18) <= pixel_out_data;
pixel_write_ena <= '1';
end if;
end if;
pixel2_write_ena <= '0';
if (pixel2_out_we = '1') then
pixel2_write_addr <= pixel2_out_x / 2;
if (pixel2_out_x mod 2 = 0) then
pixel2_write_data(17 downto 0) <= pixel2_out_data;
else
pixel2_write_data(35 downto 18) <= pixel2_out_data;
pixel2_write_ena <= '1';
end if;
end if;
end if;
end process;
ilinebuffer_hd0: entity MEM.SyncRamDual
generic map
(
DATA_WIDTH => 36,
ADDR_WIDTH => 8
)
port map
(
clk => clk100,
addr_a => pixel_write_addr,
datain_a => pixel_write_data,
dataout_a => open,
we_a => pixel_write_ena,
re_a => '0',
addr_b => pixelpos,
datain_b => (35 downto 0 => '0'),
dataout_b => linebuffer_data,
we_b => '0',
re_b => '1'
);
ilinebuffer_hd1: entity MEM.SyncRamDual
generic map
(
DATA_WIDTH => 36,
ADDR_WIDTH => 8
)
port map
(
clk => clk100,
addr_a => pixel2_write_addr,
datain_a => pixel2_write_data,
dataout_a => open,
we_a => pixel2_write_ena,
re_a => '0',
addr_b => pixelpos2,
datain_b => (35 downto 0 => '0'),
dataout_b => linebuffer2_data,
we_b => '0',
re_b => '1'
);
process (clk100)
begin
if rising_edge(clk100) then
largeimg_out_req <= '0';
newframe_sreg <= newframe_sreg(1 downto 0) & largeimg_newframe;
if (newframe_sreg(2 downto 1) = "01") then
largeimg_out_base <= (std_logic_vector(to_unsigned(16#38000000# + frameoffset * 16#400000#, 32)));
end if;
case (state) is
when IDLE =>
if (pixel_out_y_1 /= pixel_out_y and pixel_write_ena = '1' and (hdmode2x_bg = '1' or hdmode2x_obj = '1')) then
pixel_out_y_1 <= pixel_out_y;
state <= READPIXEL;
pixelpos <= 0;
pixelpos2 <= 0;
pixeladdress <= pixel_out_y * 1024;
if (pixel_out_y = 0) then
frameoffset <= current_frame;
--if (largeimg_singlebuf = '0') then
if (current_frame < 2) then
current_frame <= current_frame + 1;
else
current_frame <= 0;
end if;
--end if;
end if;
end if;
when READPIXEL =>
state <= WRITEPIXEL;
firstpixel <= '1';
when WRITEPIXEL =>
firstpixel <= '0';
if (largeimg_out_done = '1' or firstpixel = '1') then
if (pixelcnt = 0) then
pixelcnt <= 1;
pixelpos <= pixelpos + 1;
else
pixelcnt <= 0;
pixelpos2 <= pixelpos2 + 1;
if (pixelpos2 < 239) then
pixeladdress <= pixeladdress + 2;
else
state <= IDLE;
end if;
end if;
largeimg_out_req <= '1';
case (pixelcnt) is
when 0 =>
largeimg_out_addr <= "1" & std_logic_vector(to_unsigned(pixeladdress + current_frame * 16#100000#, 25));
largeimg_out_data(31 downto 0) <= x"00" & linebuffer_data( 5 downto 0) & "00" & linebuffer_data(11 downto 6) & "00" & linebuffer_data(17 downto 12) & "00";
largeimg_out_data(63 downto 32) <= x"00" & linebuffer_data(23 downto 18) & "00" & linebuffer_data(29 downto 24) & "00" & linebuffer_data(35 downto 30) & "00";
when 1 =>
largeimg_out_addr <= "1" & std_logic_vector(to_unsigned(pixeladdress + 512 + current_frame * 16#100000#, 25));
largeimg_out_data(31 downto 0) <= x"00" & linebuffer2_data( 5 downto 0) & "00" & linebuffer2_data(11 downto 6) & "00" & linebuffer2_data(17 downto 12) & "00";
largeimg_out_data(63 downto 32) <= x"00" & linebuffer2_data(23 downto 18) & "00" & linebuffer2_data(29 downto 24) & "00" & linebuffer2_data(35 downto 30) & "00";
when others => null;
end case;
end if;
end case;
end if;
end process;
end architecture;

View File

@@ -96,7 +96,6 @@ begin
cmd_burst_save := DDRAM_BURSTCNT;
cmd_din_save := DDRAM_DIN;
cmd_be_save := DDRAM_BE;
wait until rising_edge(DDRAM_CLK);
for i in 0 to (to_integer(unsigned(cmd_burst_save)) - 1) loop
if (cmd_be_save(7 downto 4) = x"F") then
data(to_integer(unsigned(cmd_address_save)) * 2 + (i * 2) + 1) := to_integer(signed(cmd_din_save(63 downto 32)));

View File

@@ -117,6 +117,12 @@ architecture arch of etb is
signal pixel_out_y : integer range 0 to 159;
signal pixel_out_data : std_logic_vector(17 downto 0);
signal pixel_out_we : std_logic;
signal largeimg_out_addr : std_logic_vector(25 downto 0);
signal largeimg_out_data : std_logic_vector(63 downto 0);
signal largeimg_out_req : std_logic;
signal largeimg_out_done : std_logic;
signal largeimg_newframe : std_logic;
signal sound_out_left : std_logic_vector(15 downto 0);
signal sound_out_right : std_logic_vector(15 downto 0);
@@ -250,9 +256,11 @@ begin
memory_remap => GBA_MemoryRemap(GBA_MemoryRemap'left),
save_state => GBA_SaveState(GBA_SaveState'left),
load_state => GBA_LoadState(GBA_LoadState'left),
interframe_blend => '0', --GBA_FrameBlend(GBA_FrameBlend'left),
interframe_blend => "00",
maxpixels => '0',
shade_mode => GBA_Pixelshade,
shade_mode => "000",
hdmode2x_bg => '1',
hdmode2x_obj => '1',
specialmodule => '0',
solar_in => "000",
tilt => '0',
@@ -333,7 +341,14 @@ begin
pixel_out_y => pixel_out_y,
pixel_out_addr => open,
pixel_out_data => pixel_out_data,
pixel_out_we => pixel_out_we,
pixel_out_we => pixel_out_we,
largeimg_out_addr => largeimg_out_addr,
largeimg_out_data => largeimg_out_data,
largeimg_out_req => largeimg_out_req,
largeimg_out_done => largeimg_out_done,
largeimg_newframe => largeimg_newframe,
largeimg_singlebuf => '0',
-- sound
sound_out_left => sound_out_left,
sound_out_right => sound_out_right,
@@ -345,6 +360,7 @@ begin
debug_mem => open --GBA_DEBUG_MEM
);
largeimg_newframe <= '1' when unsigned(largeimg_out_addr(19 downto 0)) = 0 else '0';
ch1_addr <= '0' & sdram_read_addr & "0";
ch1_req <= sdram_read_ena;
@@ -406,7 +422,12 @@ begin
ch4_din => ch4_din,
ch4_req => ch4_req,
ch4_rnw => ch4_rnw,
ch4_ready => ch4_ready
ch4_ready => ch4_ready,
ch5_addr => (27 downto 1 => '0'),
ch5_din => (63 downto 0 => '0'),
ch5_req => largeimg_out_req,
ch5_ready => largeimg_out_done
);
iddrram_model : entity tb.ddrram_model
@@ -440,6 +461,21 @@ begin
pixel_in_we => pixel_out_we
);
iframebuffer_large : entity work.framebuffer_large
generic map
(
FRAMESIZE_X => 480,
FRAMESIZE_Y => 320
)
port map
(
clk100 => clk100,
pixel_in_addr => largeimg_out_addr,
pixel_in_data => largeimg_out_data,
pixel_in_we => largeimg_out_req,
pixel_in_done => open
);
iTestprocessor : entity procbus.eTestprocessor
generic map

View File

@@ -3,9 +3,9 @@ vcom -93 -quiet -work sim/tb ^
src/tb/globals.vhd
vcom -93 -quiet -work sim/mem ^
../src/SyncRam.vhd ^
../src/SyncRamDual.vhd ^
../src/SyncRamDualNotPow2.vhd ^
../rtl/SyncRam.vhd ^
../rtl/SyncRamDual.vhd ^
../rtl/SyncRamDualNotPow2.vhd ^
src/mem/SyncRamDualByteEnable.vhd ^
src/mem/SyncFifo.vhd
@@ -23,55 +23,57 @@ vcom -quiet -work sim/reg_map ^
src/reg_map/reg_gameboy.vhd
vcom -quiet -work sim/gba ^
../src/proc_bus_gba.vhd ^
../src/cache.vhd ^
../src/reggba_timer.vhd ^
../src/reggba_keypad.vhd ^
../src/reggba_serial.vhd ^
../src/reggba_sound.vhd ^
../src/reggba_display.vhd ^
../src/reggba_dma.vhd ^
../src/reggba_system.vhd ^
../src/reg_savestates.vhd ^
../src/gba_bios_fast.vhd ^
../src/gba_reservedregs.vhd ^
../src/gba_sound_ch1.vhd ^
../src/gba_sound_ch3.vhd ^
../src/gba_sound_ch4.vhd ^
../src/gba_sound_dma.vhd ^
../src/gba_sound.vhd ^
../src/gba_joypad.vhd ^
../src/gba_serial.vhd ^
../src/gba_dma_module.vhd ^
../src/gba_dma.vhd ^
../src/gba_memorymux.vhd ^
../src/gba_timer_module.vhd ^
../src/gba_timer.vhd ^
../src/gba_gpu_timing.vhd ^
../src/gba_drawer_mode0.vhd ^
../src/gba_drawer_mode2.vhd ^
../src/gba_drawer_mode345.vhd ^
../src/gba_drawer_obj.vhd ^
../src/gba_drawer_merge.vhd ^
../src/gba_gpu_drawer.vhd ^
../src/gba_gpu_colorshade.vhd ^
../src/gba_gpu.vhd ^
../src/gba_savestates.vhd ^
../src/gba_statemanager.vhd ^
../src/gba_cheats.vhd ^
../src/gba_gpioRTCSolarGyro.vhd
../rtl/proc_bus_gba.vhd ^
../rtl/cache.vhd ^
../rtl/reggba_timer.vhd ^
../rtl/reggba_keypad.vhd ^
../rtl/reggba_serial.vhd ^
../rtl/reggba_sound.vhd ^
../rtl/reggba_display.vhd ^
../rtl/reggba_dma.vhd ^
../rtl/reggba_system.vhd ^
../rtl/reg_savestates.vhd ^
../rtl/gba_bios_fast.vhd ^
../rtl/gba_reservedregs.vhd ^
../rtl/gba_sound_ch1.vhd ^
../rtl/gba_sound_ch3.vhd ^
../rtl/gba_sound_ch4.vhd ^
../rtl/gba_sound_dma.vhd ^
../rtl/gba_sound.vhd ^
../rtl/gba_joypad.vhd ^
../rtl/gba_serial.vhd ^
../rtl/gba_dma_module.vhd ^
../rtl/gba_dma.vhd ^
../rtl/gba_memorymux.vhd ^
../rtl/gba_timer_module.vhd ^
../rtl/gba_timer.vhd ^
../rtl/gba_gpu_timing.vhd ^
../rtl/gba_drawer_mode0.vhd ^
../rtl/gba_drawer_mode2.vhd ^
../rtl/gba_drawer_mode2_2x.vhd ^
../rtl/gba_drawer_mode345.vhd ^
../rtl/gba_drawer_obj.vhd ^
../rtl/gba_drawer_merge.vhd ^
../rtl/gba_gpu_drawer.vhd ^
../rtl/gba_gpu_colorshade.vhd ^
../rtl/gba_gpu.vhd ^
../rtl/gba_savestates.vhd ^
../rtl/gba_statemanager.vhd ^
../rtl/gba_cheats.vhd ^
../rtl/gba_gpioRTCSolarGyro.vhd
vcom -2008 -quiet -work sim/gba ^
../src/gba_cpu.vhd ^
../src/gba_top.vhd
../rtl/gba_cpu.vhd ^
../rtl/gba_top.vhd
vlog -sv -quiet -work sim/top ^
../ddram.sv
../rtl/ddram.sv
vcom -quiet -work sim/tb ^
src/tb/stringprocessor.vhd ^
src/tb/tb_interpreter.vhd ^
src/tb/ddrram_model.vhd ^
src/tb/framebuffer.vhd ^
src/tb/framebuffer_large.vhd ^
src/tb/tb.vhd

View File

@@ -20,6 +20,9 @@
//============================================================================
module alsa
#(
parameter CLK_RATE = 24576000
)
(
input reset,
input clk,
@@ -139,17 +142,14 @@ always @(posedge clk) begin
end
end
localparam F48K = 48000;
localparam F50M = 50000000;
reg ce_sample;
always @(posedge clk) begin
reg [31:0] acc = 0;
ce_sample <= 0;
acc <= acc + F48K + {hurryup,6'd0};
if(acc >= F50M) begin
acc <= acc - F50M;
acc <= acc + 48000 + {hurryup,6'd0};
if(acc >= CLK_RATE) begin
acc <= acc - CLK_RATE;
ce_sample <= 1;
end
end

View File

@@ -2,258 +2,6 @@
//
// Copyright (C) 2017-2020 Sorgelig
//
//============================================================================
//////////////////////////////////////////////////////////
// DW:
// 6 : 2R 2G 2B
// 8 : 3R 3G 2B
// 9 : 3R 3G 3B
// 12 : 4R 4G 4B
// 24 : 8R 8G 8B
module arcade_video #(parameter WIDTH=320, HEIGHT=240, DW=8, GAMMA=1)
(
input clk_video,
input ce_pix,
input[DW-1:0] RGB_in,
input HBlank,
input VBlank,
input HSync,
input VSync,
output VGA_CLK,
output VGA_CE,
output [7:0] VGA_R,
output [7:0] VGA_G,
output [7:0] VGA_B,
output VGA_HS,
output VGA_VS,
output VGA_DE,
output HDMI_CLK,
output HDMI_CE,
output [7:0] HDMI_R,
output [7:0] HDMI_G,
output [7:0] HDMI_B,
output HDMI_HS,
output HDMI_VS,
output HDMI_DE,
output [1:0] HDMI_SL,
input [2:0] fx,
input forced_scandoubler,
input no_rotate,
input rotate_ccw,
inout [21:0] gamma_bus
);
wire [7:0] R,G,B;
wire CE,HS,VS,HBL,VBL;
wire [DW-1:0] RGB_fix;
wire VGA_HBL, VGA_VBL;
arcade_vga #(DW) vga
(
.clk_video(clk_video),
.ce_pix(ce_pix),
.RGB_in(RGB_in),
.HBlank(HBlank),
.VBlank(VBlank),
.HSync(HSync),
.VSync(VSync),
.RGB_out(RGB_fix),
.VGA_CLK(VGA_CLK),
.VGA_CE(CE),
.VGA_R(R),
.VGA_G(G),
.VGA_B(B),
.VGA_HS(HS),
.VGA_VS(VS),
.VGA_HBL(HBL),
.VGA_VBL(VBL)
);
wire [DW-1:0] RGB_out;
wire rhs,rvs,rhblank,rvblank;
screen_rotate #(WIDTH,HEIGHT,DW,4) rotator
(
.clk(VGA_CLK),
.ce(CE),
.ccw(rotate_ccw),
.video_in(RGB_fix),
.hblank(HBL),
.vblank(VBL),
.ce_out(CE | (~scandoubler & ~gamma_bus[19])),
.video_out(RGB_out),
.hsync(rhs),
.vsync(rvs),
.hblank_out(rhblank),
.vblank_out(rvblank)
);
generate
if(DW == 6) begin
wire [3:0] Rr = {RGB_out[5:4],RGB_out[5:4]};
wire [3:0] Gr = {RGB_out[3:2],RGB_out[3:2]};
wire [3:0] Br = {RGB_out[1:0],RGB_out[1:0]};
end
else if(DW == 8) begin
wire [3:0] Rr = {RGB_out[7:5],RGB_out[7]};
wire [3:0] Gr = {RGB_out[4:2],RGB_out[4]};
wire [3:0] Br = {RGB_out[1:0],RGB_out[1:0]};
end
else if(DW == 9) begin
wire [3:0] Rr = {RGB_out[8:6],RGB_out[8]};
wire [3:0] Gr = {RGB_out[5:3],RGB_out[5]};
wire [3:0] Br = {RGB_out[2:0],RGB_out[2]};
end
else if(DW == 12) begin
wire [3:0] Rr = RGB_out[11:8];
wire [3:0] Gr = RGB_out[7:4];
wire [3:0] Br = RGB_out[3:0];
end
else begin // 24
wire [7:0] Rr = RGB_out[23:16];
wire [7:0] Gr = RGB_out[15:8];
wire [7:0] Br = RGB_out[7:0];
end
endgenerate
assign HDMI_CLK = VGA_CLK;
assign HDMI_SL = sl[1:0];
wire [2:0] sl = fx ? fx - 1'd1 : 3'd0;
wire scandoubler = fx || forced_scandoubler;
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
(
.clk_vid(HDMI_CLK),
.ce_pix(CE | (~scandoubler & ~gamma_bus[19] & ~no_rotate)),
.ce_pix_out(HDMI_CE),
.scandoubler(scandoubler),
.hq2x(fx==1),
.gamma_bus(gamma_bus),
.R(no_rotate ? ((DW!=24) ? R[7:4] : R) : Rr),
.G(no_rotate ? ((DW!=24) ? G[7:4] : G) : Gr),
.B(no_rotate ? ((DW!=24) ? B[7:4] : B) : Br),
.HSync (no_rotate ? HS : rhs),
.VSync (no_rotate ? VS : rvs),
.HBlank(no_rotate ? HBL : rhblank),
.VBlank(no_rotate ? VBL : rvblank),
.VGA_R(HDMI_R),
.VGA_G(HDMI_G),
.VGA_B(HDMI_B),
.VGA_VS(HDMI_VS),
.VGA_HS(HDMI_HS),
.VGA_DE(HDMI_DE)
);
assign VGA_CE = no_rotate ? HDMI_CE : CE;
assign VGA_R = no_rotate ? HDMI_R : R;
assign VGA_G = no_rotate ? HDMI_G : G;
assign VGA_B = no_rotate ? HDMI_B : B;
assign VGA_HS = no_rotate ? HDMI_HS : HS;
assign VGA_VS = no_rotate ? HDMI_VS : VS;
assign VGA_DE = no_rotate ? HDMI_DE : ~(HBL | VBL);
endmodule
//////////////////////////////////////////////////////////
module arcade_vga #(parameter DW)
(
input clk_video,
input ce_pix,
input [DW-1:0] RGB_in,
input HBlank,
input VBlank,
input HSync,
input VSync,
output[DW-1:0] RGB_out,
output VGA_CLK,
output reg VGA_CE,
output [7:0] VGA_R,
output [7:0] VGA_G,
output [7:0] VGA_B,
output reg VGA_HS,
output reg VGA_VS,
output reg VGA_HBL,
output reg VGA_VBL
);
assign VGA_CLK = clk_video;
wire hs_fix,vs_fix;
sync_fix sync_v(VGA_CLK, HSync, hs_fix);
sync_fix sync_h(VGA_CLK, VSync, vs_fix);
reg [DW-1:0] RGB_fix;
always @(posedge VGA_CLK) begin
reg old_ce;
old_ce <= ce_pix;
VGA_CE <= 0;
if(~old_ce & ce_pix) begin
VGA_CE <= 1;
VGA_HS <= hs_fix;
if(~VGA_HS & hs_fix) VGA_VS <= vs_fix;
RGB_fix <= RGB_in;
VGA_HBL <= HBlank;
if(VGA_HBL & ~HBlank) VGA_VBL <= VBlank;
end
end
assign RGB_out = RGB_fix;
generate
if(DW == 6) begin
assign VGA_R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]};
assign VGA_G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]};
assign VGA_B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
end
else if(DW == 8) begin
assign VGA_R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]};
assign VGA_G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]};
assign VGA_B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
end
else if(DW == 9) begin
assign VGA_R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]};
assign VGA_G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]};
assign VGA_B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]};
end
else if(DW == 12) begin
assign VGA_R = {RGB_fix[11:8],RGB_fix[11:8]};
assign VGA_G = {RGB_fix[7:4],RGB_fix[7:4]};
assign VGA_B = {RGB_fix[3:0],RGB_fix[3:0]};
end
else begin // 24
assign VGA_R = RGB_fix[23:16];
assign VGA_G = RGB_fix[15:8];
assign VGA_B = RGB_fix[7:0];
end
endgenerate
endmodule
//============================================================================
//
// Screen +90/-90 deg. rotation
// Copyright (C) 2017-2019 Sorgelig
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
@@ -267,139 +15,278 @@ endmodule
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
//============================================================================
//
// Output timings are incompatible with any TV/VGA mode.
// The output is supposed to be send to scaler input.
//
module screen_rotate #(parameter WIDTH=320, HEIGHT=240, DEPTH=8, MARGIN=4)
//////////////////////////////////////////////////////////
// DW:
// 6 : 2R 2G 2B
// 8 : 3R 3G 2B
// 9 : 3R 3G 3B
// 12 : 4R 4G 4B
// 24 : 8R 8G 8B
module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1)
(
input clk,
input ce,
input clk_video,
input ce_pix,
input ccw,
input[DW-1:0] RGB_in,
input HBlank,
input VBlank,
input HSync,
input VSync,
input [DEPTH-1:0] video_in,
input hblank,
input vblank,
output CLK_VIDEO,
output CE_PIXEL,
output [7:0] VGA_R,
output [7:0] VGA_G,
output [7:0] VGA_B,
output VGA_HS,
output VGA_VS,
output VGA_DE,
output [1:0] VGA_SL,
input ce_out,
output [DEPTH-1:0] video_out,
output reg hsync,
output reg vsync,
output reg hblank_out,
output reg vblank_out
input [2:0] fx,
input forced_scandoubler,
inout [21:0] gamma_bus
);
localparam bufsize = WIDTH*HEIGHT;
localparam memsize = bufsize*2;
localparam aw = $clog2(memsize); // resolutions up to ~ 512x256
assign CLK_VIDEO = clk_video;
reg [aw-1:0] addr_in, addr_out;
reg we_in;
reg buff = 0;
wire hs_fix,vs_fix;
sync_fix sync_v(CLK_VIDEO, HSync, hs_fix);
sync_fix sync_h(CLK_VIDEO, VSync, vs_fix);
(* ramstyle="no_rw_check" *) reg [DEPTH-1:0] ram[memsize];
always @ (posedge clk) if (en_we) ram[addr_in] <= video_in;
always @ (posedge clk) out <= ram[addr_out];
reg [DW-1:0] RGB_fix;
reg [DEPTH-1:0] out;
reg [DEPTH-1:0] vout;
reg CE,HS,VS,HBL,VBL;
always @(posedge CLK_VIDEO) begin
reg old_ce;
old_ce <= ce_pix;
CE <= 0;
if(~old_ce & ce_pix) begin
CE <= 1;
HS <= hs_fix;
if(~HS & hs_fix) VS <= vs_fix;
assign video_out = vout;
wire en_we = ce & ~blank & en_x & en_y;
wire en_x = (xpos<WIDTH);
wire en_y = (ypos<HEIGHT);
integer xpos, ypos;
wire blank = hblank | vblank;
always @(posedge clk) begin
reg old_blank, old_vblank;
reg [aw-1:0] addr_row;
if(en_we) begin
addr_in <= ccw ? addr_in-HEIGHT[aw-1:0] : addr_in+HEIGHT[aw-1:0];
xpos <= xpos + 1;
end
old_blank <= blank;
old_vblank <= vblank;
if(~old_blank & blank) begin
xpos <= 0;
ypos <= ypos + 1;
addr_in <= ccw ? addr_row + 1'd1 : addr_row - 1'd1;
addr_row <= ccw ? addr_row + 1'd1 : addr_row - 1'd1;
end
if(~old_vblank & vblank) begin
if(buff) begin
addr_in <= ccw ? bufsize[aw-1:0]-HEIGHT[aw-1:0] : HEIGHT[aw-1:0]-1'd1;
addr_row <= ccw ? bufsize[aw-1:0]-HEIGHT[aw-1:0] : HEIGHT[aw-1:0]-1'd1;
end else begin
addr_in <= ccw ? bufsize[aw-1:0]+bufsize[aw-1:0]-HEIGHT[aw-1:0] : bufsize[aw-1:0]+HEIGHT[aw-1:0]-1'd1;
addr_row <= ccw ? bufsize[aw-1:0]+bufsize[aw-1:0]-HEIGHT[aw-1:0] : bufsize[aw-1:0]+HEIGHT[aw-1:0]-1'd1;
end
buff <= ~buff;
ypos <= 0;
xpos <= 0;
RGB_fix <= RGB_in;
HBL <= HBlank;
if(HBL & ~HBlank) VBL <= VBlank;
end
end
always @(posedge clk) begin
reg old_buff;
reg hs;
reg ced;
wire [7:0] R,G,B;
integer vbcnt;
integer xposo, yposo, xposd, yposd;
ced <= 0;
if(ce_out) begin
ced <= 1;
xposd <= xposo;
yposd <= yposo;
if(xposo == (HEIGHT + 8)) hsync <= 1;
if(xposo == (HEIGHT + 10)) hsync <= 0;
if((yposo>=MARGIN) && (yposo<WIDTH+MARGIN)) begin
if(xposo < HEIGHT) addr_out <= addr_out + 1'd1;
end
xposo <= xposo + 1;
if(xposo > (HEIGHT + 16)) begin
xposo <= 0;
if(yposo >= (WIDTH+MARGIN+MARGIN)) begin
vblank_out <= 1;
vbcnt <= vbcnt + 1;
if(vbcnt == 10 ) vsync <= 1;
if(vbcnt == 12) vsync <= 0;
end
else yposo <= yposo + 1;
old_buff <= buff;
if(old_buff != buff) begin
addr_out <= buff ? {aw{1'b0}} : bufsize[aw-1:0];
yposo <= 0;
vsync <= 0;
vbcnt <= 0;
vblank_out <= 0;
end
end
generate
if(DW == 6) begin
assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]};
assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]};
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
end
if(ced) begin
if((yposd<MARGIN) || (yposd>=WIDTH+MARGIN)) begin
vout <= 0;
end else begin
vout <= out;
else if(DW == 8) begin
assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]};
assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]};
assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]};
end
else if(DW == 9) begin
assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]};
assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]};
assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]};
end
else if(DW == 12) begin
assign R = {RGB_fix[11:8],RGB_fix[11:8]};
assign G = {RGB_fix[7:4],RGB_fix[7:4]};
assign B = {RGB_fix[3:0],RGB_fix[3:0]};
end
else begin // 24
assign R = RGB_fix[23:16];
assign G = RGB_fix[15:8];
assign B = RGB_fix[7:0];
end
endgenerate
assign VGA_SL = sl[1:0];
wire [2:0] sl = fx ? fx - 1'd1 : 3'd0;
wire scandoubler = fx || forced_scandoubler;
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
(
.clk_vid(CLK_VIDEO),
.ce_pix(CE),
.ce_pix_out(CE_PIXEL),
.scandoubler(scandoubler),
.hq2x(fx==1),
.gamma_bus(gamma_bus),
.R((DW!=24) ? R[7:4] : R),
.G((DW!=24) ? G[7:4] : G),
.B((DW!=24) ? B[7:4] : B),
.HSync (HS),
.VSync (VS),
.HBlank(HBL),
.VBlank(VBL),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_VS(VGA_VS),
.VGA_HS(VGA_HS),
.VGA_DE(VGA_DE)
);
endmodule
//============================================================================
//
// Screen +90/-90 deg. rotation
// Copyright (C) 2020 Sorgelig
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
//============================================================================
module screen_rotate
(
input CLK_VIDEO,
input CE_PIXEL,
input [7:0] VGA_R,
input [7:0] VGA_G,
input [7:0] VGA_B,
input VGA_HS,
input VGA_VS,
input VGA_DE,
input rotate_ccw,
input no_rotate,
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
input FB_VBL,
input FB_LL,
output DDRAM_CLK,
input DDRAM_BUSY,
output [7:0] DDRAM_BURSTCNT,
output [28:0] DDRAM_ADDR,
output [63:0] DDRAM_DIN,
output [7:0] DDRAM_BE,
output DDRAM_WE,
output DDRAM_RD
);
assign DDRAM_CLK = CLK_VIDEO;
assign DDRAM_BURSTCNT = 1;
assign DDRAM_ADDR = {6'b001001, i_fb, ram_addr[23:3]}; // RAM at 0x24000000
assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F;
assign DDRAM_DIN = {ram_data,ram_data};
assign DDRAM_WE = ram_wr;
assign DDRAM_RD = 0;
assign FB_EN = ~no_rotate;
assign FB_FORMAT = 5'b00110;
assign FB_BASE = {6'b001001,o_fb,24'd0};
assign FB_WIDTH = vsz;
assign FB_HEIGHT = hsz;
function [1:0] buf_next;
input [1:0] a,b;
begin
buf_next = 1;
if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2;
if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0;
end
endfunction
reg [1:0] i_fb,o_fb;
always @(posedge CLK_VIDEO) begin
reg old_vbl,old_vs;
old_vbl <= FB_VBL;
old_vs <= VGA_VS;
if(FB_LL) begin
if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]};
if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]};
end
else begin
if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb);
if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb);
end
end
reg [11:0] hsz = 320, vsz = 240;
reg [13:0] bwidth;
reg [23:0] bufsize;
always @(posedge CLK_VIDEO) begin
reg [11:0] hcnt = 0, vcnt = 0;
reg old_vs, old_de;
if(CE_PIXEL) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
hcnt <= hcnt + 1'd1;
if(~old_de & VGA_DE) begin
hcnt <= 1;
vcnt <= vcnt + 1'd1;
end
if(old_de & ~VGA_DE) hsz <= hcnt;
if(~old_vs & VGA_VS) begin
vsz <= vcnt;
vcnt <= 0;
end
bwidth <= {vsz, 2'b00} + 14'd255;
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
end
end
wire [13:0] stride = {bwidth[13:8], 8'h00};
reg [23:0] ram_addr, next_addr;
reg [31:0] ram_data;
reg ram_wr;
always @(posedge CLK_VIDEO) begin
reg [13:0] hcnt = 0;
reg old_vs, old_de;
ram_wr <= 0;
if(CE_PIXEL) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
if(~old_vs & VGA_VS) begin
next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
end
if(VGA_DE) begin
ram_wr <= 1;
ram_data <= {VGA_B,VGA_G,VGA_R};
ram_addr <= next_addr;
next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride);
end
if(old_de & ~VGA_DE) begin
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
end
if(xposd == 0) hblank_out <= 0;
if(xposd == HEIGHT) hblank_out <= 1;
end
end

View File

@@ -148,8 +148,9 @@ ENTITY ascal IS
o_hs : OUT std_logic; -- H sync
o_vs : OUT std_logic; -- V sync
o_de : OUT std_logic; -- Display Enable
o_vbl : OUT std_logic; -- V blank
o_ce : IN std_logic; -- Clock Enable
o_clk : IN std_logic; -- Output clock
o_clk : IN std_logic; -- Output clock
-- Border colour R G B
o_border : IN unsigned(23 DOWNTO 0) := x"000000";
@@ -287,7 +288,7 @@ ARCHITECTURE rtl OF ascal IS
TYPE arr_uv36 IS ARRAY (natural RANGE <>) OF unsigned(35 DOWNTO 0);
TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255;
TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12;
----------------------------------------------------------
-- Input image
SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic;
@@ -385,12 +386,12 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_run : 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);
SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0);
SIGNAL pal_idx: unsigned(7 DOWNTO 0);
SIGNAL pal_idx_lsb: std_logic;
SIGNAL pal_mem : arr_uv48(0 TO 127);
ATTRIBUTE ramstyle of pal_mem : signal is "no_rw_check";
SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0);
SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0);
SIGNAL pal_idx: unsigned(7 DOWNTO 0);
SIGNAL pal_idx_lsb: std_logic;
SIGNAL pal_mem : arr_uv48(0 TO 127);
ATTRIBUTE ramstyle of pal_mem : signal is "no_rw_check";
SIGNAL o_htotal,o_hsstart,o_hsend : uint12;
SIGNAL o_hmin,o_hmax,o_hdisp : uint12;
SIGNAL o_hsize,o_vsize : uint12;
@@ -430,7 +431,7 @@ ARCHITECTURE rtl OF ascal IS
SIGNAL o_vfrac,o_hfrac,o_hfrac1,o_hfrac2,o_hfrac3,o_hfrac4 : unsigned(11 DOWNTO 0);
SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1;
SIGNAL o_hsv,o_vsv,o_dev,o_pev : unsigned(0 TO 5);
SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 5);
SIGNAL o_hsp,o_vss : std_logic;
SIGNAL o_read,o_read_pre : std_logic;
SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2;
@@ -2049,10 +2050,10 @@ BEGIN
pal_dr<=pal_mem(to_integer(pal_a));
END IF;
END PROCESS;
pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7);
pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk);
o_fb_pal_dr_x2 <= pal_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk);
pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7);
pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk);
o_fb_pal_dr_x2 <= pal_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk);
o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0);
END GENERATE GenPal;
@@ -2152,7 +2153,7 @@ BEGIN
o_copyv(1 TO 8)<=o_copyv(0 TO 7);
o_dcptv(1)<=o_dcpt;
IF o_dcptv(1)>o_hsize THEN
IF o_dcptv(1)>=o_hsize THEN
o_copyv(2)<='0';
END IF;
o_dcptv(2)<=o_dcptv(1) MOD OHRES;
@@ -2283,6 +2284,7 @@ BEGIN
o_vcpt<=o_vcpt_pre;
END IF;
o_end(0)<=to_std_logic(o_vcpt>=o_vdisp);
o_dev(0)<=to_std_logic(o_hcpt<o_hdisp AND o_vcpt<o_vdisp);
o_pev(0)<=to_std_logic(o_hcpt>=o_hmin AND o_hcpt<=o_hmax AND
o_vcpt>=o_vmin AND o_vcpt<=o_vmax);
@@ -2296,12 +2298,14 @@ BEGIN
o_vsv(1 TO 5)<=o_vsv(0 TO 4);
o_dev(1 TO 5)<=o_dev(0 TO 4);
o_pev(1 TO 5)<=o_pev(0 TO 4);
o_end(1 TO 5)<=o_end(0 TO 4);
IF o_run='0' THEN
o_hsv(2)<='0';
o_vsv(2)<='0';
o_dev(2)<='0';
o_pev(2)<='0';
o_end(2)<='0';
END IF;
END IF;
@@ -2401,6 +2405,7 @@ BEGIN
o_hs<=o_hsv(5);
o_vs<=o_vsv(5);
o_de<=o_dev(5);
o_vbl<=o_end(5);
o_r<=x"00";
o_g<=x"00";
o_b<=x"00";

View File

@@ -1,7 +1,7 @@
module audio_out
#(
parameter CLK_RATE = 50000000
parameter CLK_RATE = 24576000
)
(
input reset,
@@ -10,8 +10,24 @@ module audio_out
//0 - 48KHz, 1 - 96KHz
input sample_rate,
input [15:0] left_in,
input [15:0] right_in,
input [31:0] flt_rate,
input [39:0] cx,
input [7:0] cx0,
input [7:0] cx1,
input [7:0] cx2,
input [23:0] cy0,
input [23:0] cy1,
input [23:0] cy2,
input [4:0] att,
input [1:0] mix,
input is_signed,
input [15:0] core_l,
input [15:0] core_r,
input [15:0] alsa_l,
input [15:0] alsa_r,
// I2S
output i2s_bclk,
@@ -56,19 +72,6 @@ always @(posedge clk) begin
end
end
reg lpf_ce;
always @(posedge clk) begin
integer div;
lpf_ce <= 0;
if(mclk_ce) begin
div <= div + 1;
if(div == FILTER_DIV) begin
div <= 0;
lpf_ce <= 1;
end
end
end
i2s i2s
(
.reset(reset),
@@ -111,47 +114,183 @@ sigma_delta_dac #(15) sd_r
.DACout(dac_r)
);
wire [15:0] al, ar;
lpf_aud lpf_l
(
.CLK(clk),
.CE(lpf_ce),
.IDATA(left_in),
.ODATA(al)
);
reg sample_ce;
always @(posedge clk) begin
reg [8:0] div = 0;
reg [1:0] add = 0;
lpf_aud lpf_r
(
.CLK(clk),
.CE(lpf_ce),
.IDATA(right_in),
.ODATA(ar)
);
div <= div + add;
if(!div) begin
div <= 2'd1 << sample_rate;
add <= 2'd1 << sample_rate;
end
endmodule
module lpf_aud
(
input CLK,
input CE,
input [15:0] IDATA,
output reg [15:0] ODATA
);
reg [511:0] acc;
reg [20:0] sum;
always @(*) begin
integer i;
sum = 0;
for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]};
sample_ce <= !div;
end
always @(posedge CLK) begin
if(CE) begin
acc <= {acc[495:0], IDATA};
ODATA <= sum[20:5];
reg flt_ce;
always @(posedge clk) begin
reg [31:0] cnt = 0;
flt_ce <= 0;
cnt = cnt + {flt_rate[30:0],1'b0};
if(cnt >= CLK_RATE) begin
cnt = cnt - CLK_RATE;
flt_ce <= 1;
end
end
reg [15:0] cl,cr;
always @(posedge clk) begin
reg [15:0] cl1,cl2;
reg [15:0] cr1,cr2;
cl1 <= core_l; cl2 <= cl1;
if(cl2 == cl1) cl <= cl2;
cr1 <= core_r; cr2 <= cr1;
if(cr2 == cr1) cr <= cr2;
end
reg a_en1 = 0, a_en2 = 0;
always @(posedge clk, posedge reset) begin
reg [1:0] dly1 = 0;
reg [14:0] dly2 = 0;
if(reset) begin
dly1 <= 0;
dly2 <= 0;
a_en1 <= 0;
a_en2 <= 0;
end
else begin
if(flt_ce) begin
if(~&dly1) dly1 <= dly1 + 1'd1;
else a_en1 <= 1;
end
if(sample_ce) begin
if(!dly2[13+sample_rate]) dly2 <= dly2 + 1'd1;
else a_en2 <= 1;
end
end
end
wire [15:0] acl, acr;
IIR_filter #(.use_params(0)) IIR_filter
(
.clk(clk),
.reset(reset),
.ce(flt_ce & a_en1),
.sample_ce(sample_ce),
.cx(cx),
.cx0(cx0),
.cx1(cx1),
.cx2(cx2),
.cy0(cy0),
.cy1(cy1),
.cy2(cy2),
.input_l({~is_signed ^ cl[15], cl[14:0]}),
.input_r({~is_signed ^ cr[15], cr[14:0]}),
.output_l(acl),
.output_r(acr)
);
wire [15:0] adl;
DC_blocker dcb_l
(
.clk(clk),
.ce(sample_ce),
.sample_rate(sample_rate),
.mute(~a_en2),
.din(acl),
.dout(adl)
);
wire [15:0] adr;
DC_blocker dcb_r
(
.clk(clk),
.ce(sample_ce),
.sample_rate(sample_rate),
.mute(~a_en2),
.din(acr),
.dout(adr)
);
wire [15:0] al, audio_l_pre;
aud_mix_top audmix_l
(
.clk(clk),
.ce(sample_ce),
.att(att),
.mix(mix),
.core_audio(adl),
.pre_in(audio_r_pre),
.linux_audio(alsa_l),
.pre_out(audio_l_pre),
.out(al)
);
wire [15:0] ar, audio_r_pre;
aud_mix_top audmix_r
(
.clk(clk),
.ce(sample_ce),
.att(att),
.mix(mix),
.core_audio(adr),
.pre_in(audio_l_pre),
.linux_audio(alsa_r),
.pre_out(audio_r_pre),
.out(ar)
);
endmodule
module aud_mix_top
(
input clk,
input ce,
input [4:0] att,
input [1:0] mix,
input [15:0] core_audio,
input [15:0] linux_audio,
input [15:0] pre_in,
output reg [15:0] pre_out = 0,
output reg [15:0] out = 0
);
reg signed [16:0] a1, a2, a3, a4;
always @(posedge clk) if (ce) begin
a1 <= {core_audio[15],core_audio};
a2 <= a1 + {linux_audio[15],linux_audio};
pre_out <= a2[16:1];
case(mix)
0: a3 <= a2;
1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]);
2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]);
3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in};
endcase
if(att[4]) a4 <= 0;
else a4 <= a3 >>> att[3:0];
//clamping
out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0];
end
endmodule

View File

@@ -279,6 +279,7 @@ always@(posedge clk_sys) begin
sd_ack_conf <= 0;
io_dout <= 0;
ps2skip <= 0;
img_mounted <= 0;
end
else if(io_strobe) begin
@@ -297,10 +298,10 @@ always@(posedge clk_sys) begin
'h2F: io_dout <= 1;
'h32: io_dout <= gamma_bus[21];
'h36: begin io_dout <= info_n; info_n <= 0; end
'h39: io_dout <= 1;
endcase
sd_buff_addr <= 0;
img_mounted <= 0;
if(io_din == 5) ps2_key_raw <= 0;
end else begin

View File

@@ -1,5 +1,6 @@
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 ]

View File

@@ -1,3 +1,4 @@
set_global_assignment -name QIP_FILE rtl/pll.qip
set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ]
set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.qip ]
set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ]

View File

@@ -17,11 +17,12 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) a
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) audio_out.v ]
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) 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 ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sd_card.v ]
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 ]

View File

@@ -12,6 +12,8 @@ derive_clock_uncertainty
set_clock_groups -exclusive \
-group [get_clocks { *|pll|pll_inst|altera_pll_i|*[*].*|divclk}] \
-group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|*[0].*|divclk}] \
-group [get_clocks { pll_audio|pll_audio_inst|altera_pll_i|*[0].*|divclk}] \
-group [get_clocks { spi_sck}] \
-group [get_clocks { *|h2f_user0_clk}] \
-group [get_clocks { FPGA_CLK1_50 }] \
-group [get_clocks { FPGA_CLK2_50 }] \
@@ -45,7 +47,8 @@ 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[*]}
set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] FB_HMIN[*] FB_HMAX[*] FB_VMIN[*] FB_VMAX[*]}
set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] FB_HMIN[*] FB_HMAX[*] FB_VMIN[*] FB_VMAX[*]}
set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]}
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*}

View File

@@ -24,6 +24,13 @@
`define USE_SDRAM
`endif
`ifndef USE_DDRAM
`ifdef USE_FB
`define USE_DDRAM
`endif
`endif
module sys_top
(
/////////// CLOCK //////////
@@ -236,7 +243,10 @@ wire io_ss0 = gp_outr[18];
wire io_ss1 = gp_outr[19];
wire io_ss2 = gp_outr[20];
`ifndef DEBUG_NOHDMI
wire io_osd_hdmi = io_ss1 & ~io_ss0;
`endif
wire io_fpga = ~io_ss1 & io_ss0;
wire io_uio = ~io_ss1 & io_ss2;
@@ -276,11 +286,16 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp
reg [15:0] cfg;
reg cfg_got = 0;
reg cfg_set = 0;
wire vga_fb = cfg[12];
wire [1:0] hdmi_limited = {cfg[11],cfg[8]};
`ifdef DEBUG_NOHDMI
wire direct_video = 1;
`else
wire direct_video = cfg[10];
`endif
wire dvi_mode = cfg[7];
wire audio_96k = cfg[6];
wire csync_en = cfg[3];
@@ -312,12 +327,24 @@ reg vs_wait = 0;
reg [11:0] vs_line = 0;
reg scaler_out = 0;
reg [31:0] aflt_rate = 7056000;
reg [39:0] acx = 4258969;
reg [7:0] acx0 = 3;
reg [7:0] acx1 = 3;
reg [7:0] acx2 = 1;
reg [23:0] acy0 = -24'd6216759;
reg [23:0] acy1 = 24'd6143386;
reg [23:0] acy2 = -24'd2023767;
reg areset = 0;
always@(posedge clk_sys) begin
reg [7:0] cmd;
reg has_cmd;
reg old_strobe;
reg [7:0] cnt = 0;
reg vs_d0,vs_d1,vs_d2;
reg [4:0] acx_att;
old_strobe <= io_strobe;
coef_wr <= 0;
@@ -325,6 +352,9 @@ always@(posedge clk_sys) begin
if(~io_uio) begin
has_cmd <= 0;
cmd <= 0;
areset <= 0;
acx_att <= 0;
acx <= acx >> acx_att;
end
else
if(~old_strobe & io_strobe) begin
@@ -333,6 +363,17 @@ always@(posedge clk_sys) begin
cmd <= io_din[7:0];
cnt <= 0;
if(io_din[7:0] == 'h30) vs_wait <= 1;
if(io_din[7:0] == 'h39) begin
aflt_rate <= 7056000;
acx <= 4258969;
acx0 <= 3;
acx1 <= 3;
acx2 <= 1;
acy0 <= -24'd6216759;
acy1 <= 24'd6143386;
acy2 <= -24'd2023767;
areset <= 1;
end
end
else begin
if(cmd == 1) begin
@@ -354,6 +395,7 @@ always@(posedge clk_sys) begin
6: if(VS != io_din[11:0]) VS <= io_din[11:0];
7: if(VBP != io_din[11:0]) VBP <= io_din[11:0];
endcase
`ifndef DEBUG_NOHDMI
if(cnt == 1) begin
cfg_custom_p1 <= 0;
cfg_custom_p2 <= 0;
@@ -369,20 +411,21 @@ always@(posedge clk_sys) begin
cnt[2:0] <= 3'b100;
end
if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14];
`endif
end
end
if(cmd == 'h2F) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: {FB_EN,FB_FLT,FB_FMT} <= {io_din[15], io_din[14], io_din[5:0]};
1: FB_BASE[15:0] <= io_din[15:0];
2: FB_BASE[31:16] <= io_din[15:0];
3: FB_WIDTH <= io_din[11:0];
4: FB_HEIGHT <= io_din[11:0];
5: FB_HMIN <= io_din[11:0];
6: FB_HMAX <= io_din[11:0];
7: FB_VMIN <= io_din[11:0];
8: FB_VMAX <= io_din[11:0];
0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]};
1: LFB_BASE[15:0] <= io_din[15:0];
2: LFB_BASE[31:16] <= io_din[15:0];
3: LFB_WIDTH <= io_din[11:0];
4: LFB_HEIGHT <= io_din[11:0];
5: LFB_HMIN <= io_din[11:0];
6: LFB_HMAX <= io_din[11:0];
7: LFB_VMIN <= io_din[11:0];
8: LFB_VMAX <= io_din[11:0];
endcase
end
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
@@ -392,6 +435,26 @@ always@(posedge clk_sys) begin
if(cmd == 'h2B) scaler_flt <= io_din[2:0];
if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]};
if(cmd == 'h38) vs_line <= io_din[11:0];
if(cmd == 'h39) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: acx_att <= io_din[4:0];
1: aflt_rate[15:0] <= io_din;
2: aflt_rate[31:16] <= io_din;
3: acx[15:0] <= io_din;
4: acx[31:16] <= io_din;
5: acx[39:32] <= io_din[7:0];
6: acx0 <= io_din[7:0];
7: acx1 <= io_din[7:0];
8: acx2 <= io_din[7:0];
9: acy0[15:0] <= io_din;
10: acy0[23:16] <= io_din[7:0];
11: acy1[15:0] <= io_din;
12: acy1[23:16] <= io_din[7:0];
13: acy2[15:0] <= io_din;
14: acy2[23:16] <= io_din[7:0];
endcase
end
end
end
@@ -402,16 +465,6 @@ always@(posedge clk_sys) begin
if(~vs_d2 & vs_d1) vs_wait <= 0;
end
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
cyclonev_hps_interface_peripheral_uart uart
(
.ri(0)
@@ -466,8 +519,6 @@ always @(posedge FPGA_CLK2_50) begin
end
wire clk_100m;
wire clk_hdmi = hdmi_clk_out;
wire clk_audio = FPGA_CLK3_50;
wire clk_pal = FPGA_CLK3_50;
//////////////////// SYSTEM MEMORY & SCALER /////////////////////////
@@ -574,7 +625,10 @@ wire [15:0] vbuf_byteenable;
wire vbuf_write;
wire [23:0] hdmi_data;
wire hdmi_vs, hdmi_hs, hdmi_de;
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl;
`ifndef DEBUG_NOHDMI
wire clk_hdmi = hdmi_clk_out;
ascal
#(
@@ -611,6 +665,7 @@ ascal
.o_hs (hdmi_hs),
.o_vs (hdmi_vs),
.o_de (hdmi_de),
.o_vbl (hdmi_vbl),
.o_lltune (lltune),
.htotal (WIDTH + HFP + HBP + HS),
.hsstart (WIDTH + HFP),
@@ -625,7 +680,7 @@ ascal
.vmin (vmin),
.vmax (vmax),
.mode ({~lowlat,FB_EN ? FB_FLT : |scaler_flt,2'b00}),
.mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}),
.poly_clk (clk_sys),
.poly_a (coef_addr),
.poly_dw (coef_data),
@@ -653,18 +708,46 @@ ascal
.avl_read (vbuf_read),
.avl_byteenable (vbuf_byteenable)
);
`endif
reg LFB_EN = 0;
reg LFB_FLT = 0;
reg [5:0] LFB_FMT = 0;
reg [11:0] LFB_WIDTH = 0;
reg [11:0] LFB_HEIGHT = 0;
reg [11:0] LFB_HMIN = 0;
reg [11:0] LFB_HMAX = 0;
reg [11:0] LFB_VMIN = 0;
reg [11:0] LFB_VMAX = 0;
reg [31:0] LFB_BASE = 0;
reg FB_EN = 0;
reg FB_FLT = 0;
reg [5:0] FB_FMT = 0;
reg [11:0] FB_WIDTH = 0;
reg [11:0] FB_HEIGHT = 0;
reg [11:0] FB_HMIN = 0;
reg [11:0] FB_HMAX = 0;
reg [11:0] FB_VMIN = 0;
reg [11:0] FB_VMAX = 0;
reg [31:0] FB_BASE = 0;
always @(posedge clk_sys) begin
FB_EN <= LFB_EN | fb_en;
if(LFB_EN) begin
FB_FMT <= LFB_FMT;
FB_WIDTH <= LFB_WIDTH;
FB_HEIGHT <= LFB_HEIGHT;
FB_BASE <= LFB_BASE;
end
else begin
FB_FMT <= fb_fmt;
FB_WIDTH <= fb_width;
FB_HEIGHT <= fb_height;
FB_BASE <= fb_base;
end
end
`ifdef USE_FB
reg fb_vbl;
always @(posedge clk_vid) fb_vbl <= hdmi_vbl;
`endif
reg [11:0] hmin;
reg [11:0] hmax;
reg [11:0] vmin;
@@ -684,11 +767,11 @@ always @(posedge clk_vid) begin
state <= state + 1'd1;
case(state)
0: if(FB_EN) begin
hmin <= FB_HMIN;
vmin <= FB_VMIN;
hmax <= FB_HMAX;
vmax <= FB_VMAX;
0: if(LFB_EN) begin
hmin <= LFB_HMIN;
vmin <= LFB_VMIN;
hmax <= LFB_HMAX;
vmax <= LFB_VMAX;
state<= 0;
end
else if(ARX && ARY && !FREESCALE) begin
@@ -712,8 +795,8 @@ always @(posedge clk_vid) begin
endcase
end
`ifndef DEBUG_NOHDMI
wire [15:0] lltune;
pll_hdmi_adj pll_hdmi_adj
(
.clk(FPGA_CLK1_50),
@@ -731,6 +814,9 @@ pll_hdmi_adj pll_hdmi_adj
.o_address(cfg_address),
.o_writedata(cfg_data)
);
`else
assign led_locked = 0;
`endif
wire [63:0] pal_data;
wire [47:0] pal_d = {pal_data[55:32], pal_data[23:0]};
@@ -750,7 +836,7 @@ end
///////////////////////// HDMI output /////////////////////////////////
`ifndef DEBUG_NOHDMI
wire hdmi_clk_out;
pll_hdmi pll_hdmi
(
@@ -760,6 +846,7 @@ pll_hdmi pll_hdmi
.reconfig_from_pll(reconfig_from_pll),
.outclk_0(hdmi_clk_out)
);
`endif
//1920x1080@60 PCLK=148.5MHz CEA
reg [11:0] WIDTH = 1920;
@@ -781,6 +868,7 @@ reg adj_write;
reg [5:0] adj_address;
reg [31:0] adj_data;
`ifndef DEBUG_NOHDMI
pll_cfg pll_cfg
(
.mgmt_clk(FPGA_CLK1_50),
@@ -795,8 +883,18 @@ pll_cfg pll_cfg
.reconfig_from_pll(reconfig_from_pll)
);
reg cfg_ready = 0;
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
reg cfg_ready = 0;
always @(posedge FPGA_CLK1_50) begin
reg gotd = 0, gotd2 = 0;
reg custd = 0, custd2 = 0;
@@ -825,6 +923,12 @@ always @(posedge FPGA_CLK1_50) begin
if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1;
end
`else
wire cfg_ready = 1;
`endif
wire hdmi_config_done;
hdmi_config hdmi_config
(
@@ -841,6 +945,7 @@ hdmi_config hdmi_config
.ypbpr(ypbpr_en & direct_video)
);
`ifndef DEBUG_NOHDMI
wire [23:0] hdmi_data_sl;
wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl;
scanlines #(1) HDMI_scanlines
@@ -861,6 +966,7 @@ scanlines #(1) HDMI_scanlines
wire [23:0] hdmi_data_osd;
wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd;
osd hdmi_osd
(
.clk_sys(clk_sys),
@@ -884,6 +990,7 @@ osd hdmi_osd
.osd_status(osd_status)
`endif
);
`endif
wire hdmi_cs_osd;
csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd);
@@ -930,12 +1037,16 @@ always @(posedge clk_vid) begin
end
wire hdmi_tx_clk;
`ifndef 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)
);
`else
assign hdmi_tx_clk = clk_vid;
`endif
altddio_out
#(
@@ -1082,65 +1193,60 @@ end
assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ;
`ifndef DUAL_SDRAM
wire anl,anr;
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 : anr;
assign AUDIO_L = SW[3] ? 1'bZ : SW[0] ? HDMI_SCLK : anl;
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;
`endif
assign HDMI_MCLK = 0;
assign HDMI_MCLK = clk_audio;
wire clk_audio;
wire [15:0] audio_l, audio_l_pre;
aud_mix_top audmix_l
pll_audio pll_audio
(
.clk(clk_audio),
.att(vol_att),
.mix(audio_mix),
.is_signed(audio_s),
.core_audio(audio_ls),
.pre_in(audio_r_pre),
.linux_audio(alsa_l),
.pre_out(audio_l_pre),
.out(audio_l)
);
wire [15:0] audio_r, audio_r_pre;
aud_mix_top audmix_r
(
.clk(clk_audio),
.att(vol_att),
.mix(audio_mix),
.is_signed(audio_s),
.core_audio(audio_rs),
.pre_in(audio_l_pre),
.linux_audio(alsa_r),
.pre_out(audio_r_pre),
.out(audio_r)
.refclk(FPGA_CLK3_50),
.rst(0),
.outclk_0(clk_audio)
);
wire spdif;
audio_out audio_out
(
.reset(reset),
.reset(reset | areset),
.clk(clk_audio),
.att(vol_att),
.mix(audio_mix),
.sample_rate(audio_96k),
.left_in(audio_l),
.right_in(audio_r),
.flt_rate(aflt_rate),
.cx(acx),
.cx0(acx0),
.cx1(acx1),
.cx2(acx2),
.cy0(acy0),
.cy1(acy1),
.cy2(acy2),
.is_signed(audio_s),
.core_l(audio_l),
.core_r(audio_r),
.alsa_l(alsa_l),
.alsa_r(alsa_r),
.i2s_bclk(HDMI_SCLK),
.i2s_lrclk(HDMI_LRCLK),
.i2s_data(HDMI_I2S),
`ifndef DUAL_SDRAM
.dac_l(anl),
.dac_r(anr),
.dac_l(analog_l),
.dac_r(analog_r),
`endif
.spdif(spdif)
);
wire [28:0] alsa_address;
wire [63:0] alsa_readdata;
wire alsa_ready;
@@ -1168,7 +1274,6 @@ alsa alsa
.pcm_r(alsa_r)
);
//////////////// User I/O (USB 3.0 connector) /////////////////////////
assign USER_IO[0] = !user_out[0] ? 1'b0 : 1'bZ;
@@ -1191,7 +1296,7 @@ assign user_in[6] = USER_IO[6];
/////////////////// User module connection ////////////////////////////
wire clk_sys;
wire [15:0] audio_ls, audio_rs;
wire [15:0] audio_l, audio_r;
wire audio_s;
wire [1:0] audio_mix;
wire [1:0] scanlines;
@@ -1227,24 +1332,20 @@ wire [6:0] user_out, user_in;
assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = {39'bZ};
`endif
`ifdef ARCADE_SYS
wire hvs_emu, hhs_emu;
sync_fix hdmi_sync_v(clk_ihdmi, hvs_emu, hvs_fix);
sync_fix hdmi_sync_h(clk_ihdmi, hhs_emu, hhs_fix);
assign clk_ihdmi= clk_vid;
assign ce_hpix = ce_pix;
assign hr_out = r_out;
assign hg_out = g_out;
assign hb_out = b_out;
assign hhs_fix = hs_fix;
assign hvs_fix = vs_fix;
assign hde_emu = de_emu;
`ifdef ARCADE_SYS
assign audio_mix = 0;
assign {ADC_SCK, ADC_SDI, ADC_CONVST} = 0;
assign btn = 0;
`else
assign clk_ihdmi= clk_vid;
assign ce_hpix = ce_pix;
assign hr_out = r_out;
assign hg_out = g_out;
assign hb_out = b_out;
assign hhs_fix = hs_fix;
assign hvs_fix = vs_fix;
assign hde_emu = de_emu;
wire uart_dtr;
wire uart_dsr;
wire uart_cts;
@@ -1254,6 +1355,19 @@ assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQM
wire osd_status;
`endif
wire fb_en;
wire [4:0] fb_fmt;
wire [11:0] fb_width;
wire [11:0] fb_height;
wire [31:0] fb_base;
`ifndef USE_FB
assign fb_en = 0;
assign fb_fmt = 0;
assign fb_width = 0;
assign fb_height = 0;
assign fb_base = 0;
`endif
emu emu
(
@@ -1269,39 +1383,36 @@ emu emu
.VGA_DE(de_emu),
.VGA_F1(f1),
`ifdef ARCADE_SYS
.VGA_CLK(clk_vid),
.VGA_CE(ce_pix),
.HDMI_CLK(clk_ihdmi),
.HDMI_CE(ce_hpix),
.HDMI_R(hr_out),
.HDMI_G(hg_out),
.HDMI_B(hb_out),
.HDMI_HS(hhs_emu),
.HDMI_VS(hvs_emu),
.HDMI_DE(hde_emu),
.HDMI_SL(scanlines),
.HDMI_ARX(ARX),
.HDMI_ARY(ARY),
`else
.CLK_VIDEO(clk_vid),
.CE_PIXEL(ce_pix),
.VGA_SL(scanlines),
.VIDEO_ARX(ARX),
.VIDEO_ARY(ARY),
.AUDIO_MIX(audio_mix),
.ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}),
`ifdef USE_FB
.FB_EN(fb_en),
.FB_FORMAT(fb_fmt),
.FB_WIDTH(fb_width),
.FB_HEIGHT(fb_height),
.FB_BASE(fb_base),
.FB_VBL(fb_vbl),
.FB_LL(lowlat),
`endif
.LED_USER(led_user),
.LED_POWER(led_power),
.LED_DISK(led_disk),
.AUDIO_L(audio_ls),
.AUDIO_R(audio_rs),
.CLK_AUDIO(clk_audio),
.AUDIO_L(audio_l),
.AUDIO_R(audio_r),
.AUDIO_S(audio_s),
`ifndef ARCADE_SYS
.AUDIO_MIX(audio_mix),
.ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}),
`endif
`ifdef USE_DDRAM
.DDRAM_CLK(ram_clk),
.DDRAM_ADDR(ram_address),
@@ -1401,56 +1512,6 @@ endmodule
/////////////////////////////////////////////////////////////////////
module aud_mix_top
(
input clk,
input [4:0] att,
input [1:0] mix,
input is_signed,
input [15:0] core_audio,
input [15:0] linux_audio,
input [15:0] pre_in,
output reg [15:0] pre_out,
output reg [15:0] out
);
reg [15:0] ca;
always @(posedge clk) begin
reg [15:0] d1,d2,d3;
d1 <= core_audio; d2<=d1; d3<=d2;
if(d2 == d3) ca <= d2;
end
always @(posedge clk) begin
reg signed [16:0] a1, a2, a3, a4;
a1 <= is_signed ? {ca[15],ca} : {2'b00,ca[15:1]};
a2 <= a1 + {linux_audio[15],linux_audio};
pre_out <= a2[16:1];
case(mix)
0: a3 <= a2;
1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]);
2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]);
3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in};
endcase
if(att[4]) a4 <= 0;
else a4 <= a3 >>> att[3:0];
//clamping
out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0];
end
endmodule
/////////////////////////////////////////////////////////////////////
// CSync generation
// Shifts HSync left by 1 HSync period during VSync