mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-06 08:04:41 +00:00
[Gameboy] Update from MiSTer
This commit is contained in:
170
cores/gameboy/dpram.vhd
Normal file
170
cores/gameboy/dpram.vhd
Normal file
@@ -0,0 +1,170 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
ENTITY dpram IS
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock_a : IN STD_LOGIC;
|
||||
clken_a : IN STD_LOGIC := '1';
|
||||
address_a : IN STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data_a : IN STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
wren_a : IN STD_LOGIC := '0';
|
||||
q_a : OUT STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
|
||||
clock_b : IN STD_LOGIC;
|
||||
clken_b : IN STD_LOGIC := '1';
|
||||
address_b : IN STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data_b : IN STD_LOGIC_VECTOR (data_width-1 DOWNTO 0) := (others => '0');
|
||||
wren_b : IN STD_LOGIC := '0';
|
||||
q_b : OUT STD_LOGIC_VECTOR (data_width-1 DOWNTO 0)
|
||||
);
|
||||
END dpram;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram IS
|
||||
BEGIN
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_input_b => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width,
|
||||
numwords_b => 2**addr_width,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
outdata_reg_b => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
widthad_a => addr_width,
|
||||
widthad_b => addr_width,
|
||||
width_a => data_width,
|
||||
width_b => data_width,
|
||||
width_byteena_a => 1,
|
||||
width_byteena_b => 1,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
clock0 => clock_a,
|
||||
clock1 => clock_b,
|
||||
clocken0 => clken_a,
|
||||
clocken1 => clken_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
wren_a => wren_a,
|
||||
wren_b => wren_b,
|
||||
q_a => q_a,
|
||||
q_b => q_b
|
||||
);
|
||||
|
||||
END SYN;
|
||||
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Dual port Block RAM different parameters on ports
|
||||
--------------------------------------------------------------
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
entity dpram_dif is
|
||||
generic (
|
||||
addr_width_a : integer := 8;
|
||||
data_width_a : integer := 8;
|
||||
addr_width_b : integer := 8;
|
||||
data_width_b : integer := 8;
|
||||
mem_init_file : string := " "
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : in STD_LOGIC;
|
||||
|
||||
address_a : in STD_LOGIC_VECTOR (addr_width_a-1 DOWNTO 0);
|
||||
data_a : in STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0) := (others => '0');
|
||||
enable_a : in STD_LOGIC := '1';
|
||||
wren_a : in STD_LOGIC := '0';
|
||||
q_a : out STD_LOGIC_VECTOR (data_width_a-1 DOWNTO 0);
|
||||
cs_a : in std_logic := '1';
|
||||
|
||||
address_b : in STD_LOGIC_VECTOR (addr_width_b-1 DOWNTO 0) := (others => '0');
|
||||
data_b : in STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0) := (others => '0');
|
||||
enable_b : in STD_LOGIC := '1';
|
||||
wren_b : in STD_LOGIC := '0';
|
||||
q_b : out STD_LOGIC_VECTOR (data_width_b-1 DOWNTO 0);
|
||||
cs_b : in std_logic := '1'
|
||||
);
|
||||
end entity;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF dpram_dif IS
|
||||
|
||||
signal q0 : std_logic_vector((data_width_a - 1) downto 0);
|
||||
signal q1 : std_logic_vector((data_width_b - 1) downto 0);
|
||||
|
||||
BEGIN
|
||||
q_a<= q0 when cs_a = '1' else (others => '1');
|
||||
q_b<= q1 when cs_b = '1' else (others => '1');
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
address_reg_b => "CLOCK1",
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_input_b => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
clock_enable_output_b => "BYPASS",
|
||||
indata_reg_b => "CLOCK1",
|
||||
intended_device_family => "Cyclone V",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width_a,
|
||||
numwords_b => 2**addr_width_b,
|
||||
operation_mode => "BIDIR_DUAL_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_aclr_b => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
outdata_reg_b => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ",
|
||||
init_file => mem_init_file,
|
||||
widthad_a => addr_width_a,
|
||||
widthad_b => addr_width_b,
|
||||
width_a => data_width_a,
|
||||
width_b => data_width_b,
|
||||
width_byteena_a => 1,
|
||||
width_byteena_b => 1,
|
||||
wrcontrol_wraddress_reg_b => "CLOCK1"
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address_a,
|
||||
address_b => address_b,
|
||||
clock0 => clock,
|
||||
clock1 => clock,
|
||||
clocken0 => enable_a,
|
||||
clocken1 => enable_b,
|
||||
data_a => data_a,
|
||||
data_b => data_b,
|
||||
wren_a => wren_a and cs_a,
|
||||
wren_b => wren_b and cs_b,
|
||||
q_a => q0,
|
||||
q_b => q1
|
||||
);
|
||||
|
||||
END SYN;
|
||||
@@ -171,22 +171,22 @@ set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
set_global_assignment -name VERILOG_FILE gb_mist.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE sdram.sv
|
||||
set_global_assignment -name VERILOG_FILE sigma_delta_dac.v
|
||||
set_global_assignment -name VHDL_FILE gbc_snd.vhd
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
set_global_assignment -name VERILOG_FILE user_io.v
|
||||
set_global_assignment -name VERILOG_FILE osd.v
|
||||
set_global_assignment -name QIP_FILE pll.qip
|
||||
set_global_assignment -name VERILOG_FILE gb.v
|
||||
set_global_assignment -name VERILOG_FILE lcd.v
|
||||
set_global_assignment -name QIP_FILE boot_rom.qip
|
||||
set_global_assignment -name VHDL_FILE spram.vhd
|
||||
set_global_assignment -name VHDL_FILE dpram.vhd
|
||||
set_global_assignment -name VHDL_FILE gbc_snd.vhd
|
||||
set_global_assignment -name VERILOG_FILE gb.v
|
||||
set_global_assignment -name VERILOG_FILE video.v
|
||||
set_global_assignment -name VERILOG_FILE hdma.v
|
||||
set_global_assignment -name VERILOG_FILE sprites.v
|
||||
set_global_assignment -name VERILOG_FILE sprite.v
|
||||
set_global_assignment -name VERILOG_FILE sprite_sort.v
|
||||
set_global_assignment -name VERILOG_FILE timer.v
|
||||
set_global_assignment -name QIP_FILE iram.qip
|
||||
set_global_assignment -name QIP_FILE vram.qip
|
||||
set_global_assignment -name QIP_FILE zpram.qip
|
||||
set_global_assignment -name QIP_FILE boot_rom.qip
|
||||
set_global_assignment -name VHDL_FILE t80/T80.vhd
|
||||
set_global_assignment -name VHDL_FILE t80/Z80.vhd
|
||||
set_global_assignment -name VHDL_FILE t80/T80_Reg.vhd
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
|
||||
module gb (
|
||||
input reset,
|
||||
input clk,
|
||||
|
||||
input clk,
|
||||
input clk2x,
|
||||
|
||||
input fast_boot,
|
||||
input [7:0] joystick,
|
||||
|
||||
input isGBC,
|
||||
input isGBC_game,
|
||||
|
||||
// cartridge interface
|
||||
// can adress up to 1MB ROM
|
||||
output [15:0] cart_addr,
|
||||
@@ -33,16 +36,22 @@ module gb (
|
||||
output cart_wr,
|
||||
input [7:0] cart_do,
|
||||
output [7:0] cart_di,
|
||||
|
||||
|
||||
//gbc bios interface
|
||||
output [11:0] gbc_bios_addr,
|
||||
input [7:0] gbc_bios_do,
|
||||
|
||||
// audio
|
||||
output [15:0] audio_l,
|
||||
output [15:0] audio_r,
|
||||
|
||||
// lcd interface
|
||||
output lcd_clkena,
|
||||
output [1:0] lcd_data,
|
||||
output [14:0] lcd_data,
|
||||
output [1:0] lcd_mode,
|
||||
output lcd_on
|
||||
output lcd_on,
|
||||
|
||||
output speed //GBC
|
||||
);
|
||||
|
||||
// include cpu
|
||||
@@ -50,9 +59,11 @@ wire [15:0] cpu_addr;
|
||||
wire [7:0] cpu_do;
|
||||
|
||||
wire sel_timer = (cpu_addr[15:4] == 12'hff0) && (cpu_addr[3:2] == 2'b01);
|
||||
wire sel_video_reg = cpu_addr[15:4] == 12'hff4;
|
||||
wire sel_video_reg = (cpu_addr[15:4] == 12'hff4) || (isGBC && (cpu_addr[15:2] == 14'h3fda)); //video and oam dma (+ ff68-ff6B when gbc)
|
||||
wire sel_video_oam = cpu_addr[15:8] == 8'hfe;
|
||||
wire sel_joy = cpu_addr == 16'hff00; // joystick controller
|
||||
wire sel_sb = cpu_addr == 16'hff01; // serial SB - Serial transfer data
|
||||
wire sel_sc = cpu_addr == 16'hff02; // SC - Serial Transfer Control (R/W)
|
||||
wire sel_rom = !cpu_addr[15]; // lower 32k are rom
|
||||
wire sel_cram = cpu_addr[15:13] == 3'b101; // 8k cart ram at $a000
|
||||
wire sel_vram = cpu_addr[15:13] == 3'b100; // 8k video ram at $8000
|
||||
@@ -63,26 +74,55 @@ wire sel_zpram = (cpu_addr[15:7] == 9'b111111111) && // 127 bytes zero pageram a
|
||||
(cpu_addr != 16'hffff);
|
||||
wire sel_audio = (cpu_addr[15:8] == 8'hff) && // audio reg ff10 - ff3f
|
||||
((cpu_addr[7:5] == 3'b001) || (cpu_addr[7:4] == 4'b0001));
|
||||
|
||||
//DMA can select from $0000 to $F100
|
||||
wire dma_sel_rom = !dma_addr[15]; // lower 32k are rom
|
||||
wire dma_sel_cram = dma_addr[15:13] == 3'b101; // 8k cart ram at $a000
|
||||
wire dma_sel_vram = dma_addr[15:13] == 3'b100; // 8k video ram at $8000
|
||||
wire dma_sel_iram = (dma_addr[15:14] == 2'b11) && (dma_addr[15:8] != 8'hff); // 8k internal ram at $c000
|
||||
|
||||
//CGB
|
||||
wire sel_vram_bank = (cpu_addr==16'hff4f);
|
||||
wire sel_iram_bank = (cpu_addr==16'hff70);
|
||||
wire sel_hdma = (cpu_addr[15:4]==12'hff5) &&
|
||||
((cpu_addr[3:0]!=4'd0)&&(cpu_addr[3:0]< 4'd6)); //HDMA FF51-FF55
|
||||
wire sel_key1 = cpu_addr == 16'hff4d; // KEY1 - CGB Mode Only - Prepare Speed Switch
|
||||
wire sel_rp = cpu_addr == 16'hff56; //FF56 - RP - CGB Mode Only - Infrared Communications Port
|
||||
|
||||
//HDMA can select from $0000 to $7ff0 or A000-DFF0
|
||||
wire hdma_sel_rom = !hdma_source_addr[15]; // lower 32k are rom
|
||||
wire hdma_sel_cram = hdma_source_addr[15:13] == 3'b101; // 8k cart ram at $a000
|
||||
wire hdma_sel_iram = hdma_source_addr[15:13] == 3'b110; // 8k internal ram at $c000-$dff0
|
||||
|
||||
|
||||
// the boot roms sees a special $42 flag in $ff50 if it's supposed to to a fast boot
|
||||
wire sel_fast = fast_boot && cpu_addr == 16'hff50 && boot_rom_enabled;
|
||||
|
||||
|
||||
wire [7:0] sc_r = {sc_start,6'h3F,sc_shiftclock};
|
||||
|
||||
// http://gameboy.mongenel.com/dmg/asmmemmap.html
|
||||
wire [7:0] cpu_di =
|
||||
irq_ack?irq_vec:
|
||||
sel_fast?8'h42: // fast boot flag
|
||||
sel_if?{3'b111, if_r}: // interrupt flag register
|
||||
isGBC&&sel_rp?8'h02:
|
||||
isGBC&&sel_iram_bank?{5'h1f,iram_bank}:
|
||||
isGBC&&sel_vram_bank?{7'h7f,vram_bank}:
|
||||
isGBC&&sel_hdma?{hdma_do}: //hdma GBC
|
||||
isGBC&&sel_key1?{cpu_speed,6'h3f,prepare_switch}: //key1 cpu speed register(GBC)
|
||||
sel_joy?joy_do: // joystick register
|
||||
sel_sb?8'hFF: // serial transfer data register
|
||||
sel_sc?sc_r: // serial transfer control register
|
||||
sel_timer?timer_do: // timer registers
|
||||
sel_video_reg?video_do: // video registers
|
||||
sel_video_oam?video_do: // video object attribute memory
|
||||
sel_audio?audio_do: // audio registers
|
||||
sel_rom?rom_do: // boot rom + cartridge rom
|
||||
sel_cram?rom_do: // cartridge ram
|
||||
sel_vram?vram_do: // vram
|
||||
sel_audio?audio_do: // audio registers
|
||||
sel_rom?rom_do: // boot rom + cartridge rom
|
||||
sel_cram?rom_do: // cartridge ram
|
||||
sel_vram?(isGBC&&vram_bank)?vram1_do:vram_do: // vram (GBC bank 0+1)
|
||||
sel_zpram?zpram_do: // zero page ram
|
||||
sel_iram?iram_do: // internal ram
|
||||
sel_ie?{3'b000, ie_r}: // interrupt enable register
|
||||
sel_if?{3'b000, if_r}: // interrupt flag register
|
||||
8'hff;
|
||||
|
||||
wire cpu_wr_n;
|
||||
@@ -90,11 +130,14 @@ wire cpu_rd_n;
|
||||
wire cpu_iorq_n;
|
||||
wire cpu_m1_n;
|
||||
wire cpu_mreq_n;
|
||||
|
||||
wire cpu_clken = isGBC ? !hdma_rd:1'b1; //when hdma is enabled stop CPU (GBC)
|
||||
wire cpu_stop;
|
||||
|
||||
GBse cpu (
|
||||
.RESET_n ( !reset ),
|
||||
.CLK_n ( clk ),
|
||||
.CLKEN ( 1'b1 ),
|
||||
.CLK_n ( clk_cpu ),
|
||||
.CLKEN ( cpu_clken ),
|
||||
.WAIT_n ( 1'b1 ),
|
||||
.INT_n ( irq_n ),
|
||||
.NMI_n ( 1'b1 ),
|
||||
@@ -109,9 +152,34 @@ GBse cpu (
|
||||
.BUSAK_n ( ),
|
||||
.A ( cpu_addr ),
|
||||
.DI ( cpu_di ),
|
||||
.DO ( cpu_do )
|
||||
.DO ( cpu_do ),
|
||||
.STOP ( cpu_stop )
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// --------------------- Speed Toggle KEY1 (GBC)-----------------------
|
||||
// --------------------------------------------------------------------
|
||||
wire clk_cpu = cpu_speed?clk2x:clk;
|
||||
//wire clk_cpu = clk;
|
||||
reg cpu_speed; // - 0 Normal mode (4MHz) - 1 Double Speed Mode (8MHz)
|
||||
reg prepare_switch; // set to 1 to toggle speed
|
||||
assign speed = cpu_speed;
|
||||
|
||||
always @(posedge clk2x) begin
|
||||
if(reset) begin
|
||||
cpu_speed <= 1'b0;
|
||||
prepare_switch <= 1'b0;
|
||||
end else if (sel_key1 && !cpu_wr_n && isGBC)begin
|
||||
prepare_switch <= cpu_do[0];
|
||||
end
|
||||
|
||||
if (isGBC && prepare_switch && cpu_stop) begin
|
||||
cpu_speed <= !cpu_speed;
|
||||
prepare_switch <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ------------------------------ audio -------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
@@ -121,7 +189,7 @@ wire audio_wr = !cpu_wr_n && sel_audio;
|
||||
wire [7:0] audio_do;
|
||||
|
||||
gbc_snd audio (
|
||||
.clk ( clk ),
|
||||
.clk ( clk2x ),
|
||||
.reset ( reset ),
|
||||
|
||||
.s1_read ( audio_rd ),
|
||||
@@ -134,23 +202,62 @@ gbc_snd audio (
|
||||
.snd_right ( audio_r )
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// -----------------------serial port(dummy)---------------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
reg [3:0] serial_counter;
|
||||
reg sc_start,sc_shiftclock;
|
||||
|
||||
reg serial_irq;
|
||||
reg [8:0] serial_clk_div; //8192Hz
|
||||
|
||||
always @(posedge clk_cpu) begin
|
||||
serial_irq <= 1'b0;
|
||||
if(reset) begin
|
||||
sc_start <= 1'b0;
|
||||
sc_shiftclock <= 1'b0;
|
||||
end else if (sel_sc && !cpu_wr_n) begin //cpu write
|
||||
sc_start <= cpu_do[7];
|
||||
sc_shiftclock <= cpu_do[0];
|
||||
if (cpu_do[7]) begin //enable transfer
|
||||
serial_clk_div <= 9'h1FF;
|
||||
serial_counter <= 4'd8;
|
||||
end
|
||||
end else if (sc_start && sc_shiftclock) begin // serial transfer and serial clock enabled
|
||||
|
||||
serial_clk_div <= serial_clk_div - 9'd1;
|
||||
|
||||
if (serial_clk_div == 9'd0 && serial_counter)
|
||||
serial_counter <= serial_counter - 4'd1;
|
||||
|
||||
if (!serial_counter) begin
|
||||
serial_irq <= 1'b1; //trigger interrupt
|
||||
sc_start <= 1'b0; //reset transfer state
|
||||
serial_clk_div <= 9'h1FF;
|
||||
serial_counter <= 4'd8;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ------------------------------ inputs ------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
wire [3:0] joy_p4 = { !joystick[2], !joystick[3], !joystick[1], !joystick[0] };
|
||||
wire [3:0] joy_p5 = { !joystick[7], !joystick[6], !joystick[5], !joystick[4] };
|
||||
reg [1:0] p54;
|
||||
wire [3:0] joy_p4 = ~{ joystick[2], joystick[3], joystick[1], joystick[0] } | {4{p54[0]}};
|
||||
wire [3:0] joy_p5 = ~{ joystick[7], joystick[6], joystick[5], joystick[4] } | {4{p54[1]}};
|
||||
reg [1:0] p54;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset)
|
||||
p54 <= 2'b11;
|
||||
else if(sel_joy && !cpu_wr_n)
|
||||
p54 <= cpu_do[5:4];
|
||||
always @(posedge clk_cpu) begin
|
||||
if(reset) p54 <= 2'b00;
|
||||
else if(sel_joy && !cpu_wr_n) p54 <= cpu_do[5:4];
|
||||
end
|
||||
|
||||
wire [7:0] joy_do = { 2'b11, p54,
|
||||
((!p54[0])?joy_p4:4'hf) & ((!p54[1])?joy_p5:4'hf) };
|
||||
wire [7:0] joy_do = { 2'b11, p54, joy_p4 & joy_p5 };
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ---------------------------- interrupts ----------------------------
|
||||
@@ -162,27 +269,27 @@ wire [7:0] joy_do = { 2'b11, p54,
|
||||
|
||||
wire irq_ack = !cpu_iorq_n && !cpu_m1_n;
|
||||
|
||||
// latch irq vector at the begin of the irq ack
|
||||
reg [7:0] irq_vec;
|
||||
always @(posedge irq_ack)
|
||||
irq_vec <=
|
||||
if_r[0]?8'h40: // vsync
|
||||
if_r[1]?8'h48: // lcdc
|
||||
if_r[2]?8'h50: // timer
|
||||
if_r[3]?8'h58: // serial
|
||||
if_r[4]?8'h60: // input
|
||||
8'h55;
|
||||
// irq vector
|
||||
wire [7:0] irq_vec =
|
||||
if_r[0]&&ie_r[0]?8'h40: // vsync
|
||||
if_r[1]&&ie_r[1]?8'h48: // lcdc
|
||||
if_r[2]&&ie_r[2]?8'h50: // timer
|
||||
if_r[3]&&ie_r[3]?8'h58: // serial
|
||||
if_r[4]&&ie_r[4]?8'h60: // input
|
||||
8'h55;
|
||||
|
||||
wire vs = (lcd_mode == 2'b01);
|
||||
reg vsD, vsD2;
|
||||
reg [3:0] inputD, inputD2;
|
||||
reg [7:0] inputD, inputD2;
|
||||
|
||||
// irq is low when an enable irq is active
|
||||
wire irq_n = !(ie_r & if_r);
|
||||
|
||||
reg [4:0] if_r;
|
||||
reg [4:0] ie_r; // writing $ffff sets the irq enable mask
|
||||
always @(posedge clk) begin
|
||||
always @(negedge clk_cpu) begin //negedge to trigger interrupt earlier
|
||||
reg old_ack = 0;
|
||||
|
||||
if(reset) begin
|
||||
ie_r <= 5'h00;
|
||||
if_r <= 5'h00;
|
||||
@@ -198,15 +305,20 @@ always @(posedge clk) begin
|
||||
|
||||
// timer_irq already is a 1 clock event
|
||||
if(timer_irq) if_r[2] <= 1'b1;
|
||||
|
||||
// serial irq already is a 1 clock event
|
||||
if(serial_irq) if_r[3] <= 1'b1;
|
||||
|
||||
// falling edge on any input line P10..P13
|
||||
inputD <= joy_p4 | joy_p5;
|
||||
inputD <= {joy_p4, joy_p5};
|
||||
inputD2 <= inputD;
|
||||
if(~inputD & inputD2) if_r[4] <= 1'b1;
|
||||
|
||||
// cpu acknowledges irq. this clears the active irq with hte
|
||||
// highest priority
|
||||
if(irq_ack) begin
|
||||
old_ack <= irq_ack;
|
||||
|
||||
if(old_ack & ~irq_ack) begin
|
||||
if(if_r[0] && ie_r[0]) if_r[0] <= 1'b0;
|
||||
else if(if_r[1] && ie_r[1]) if_r[1] <= 1'b0;
|
||||
else if(if_r[2] && ie_r[2]) if_r[2] <= 1'b0;
|
||||
@@ -231,7 +343,7 @@ wire timer_irq;
|
||||
wire [7:0] timer_do;
|
||||
timer timer (
|
||||
.reset ( reset ),
|
||||
.clk ( clk ),
|
||||
.clk ( clk_cpu ), //2x in fast mode
|
||||
|
||||
.irq ( timer_irq ),
|
||||
|
||||
@@ -252,11 +364,15 @@ wire [7:0] video_do;
|
||||
wire [12:0] video_addr;
|
||||
wire [15:0] dma_addr;
|
||||
wire video_rd, dma_rd;
|
||||
wire [7:0] dma_data = (dma_addr[15:14]==2'b11)?iram_do:cart_do;
|
||||
wire [7:0] dma_data = dma_sel_iram?iram_do:dma_sel_vram?(isGBC&&vram_bank)?vram1_do:vram_do:cart_do;
|
||||
|
||||
|
||||
video video (
|
||||
.reset ( reset ),
|
||||
.clk ( clk ),
|
||||
.clk_reg ( clk_cpu ), //can be 2x in cgb double speed mode
|
||||
.isGBC ( isGBC ),
|
||||
|
||||
|
||||
.irq ( video_irq ),
|
||||
|
||||
@@ -276,23 +392,86 @@ video video (
|
||||
.vram_addr ( video_addr ),
|
||||
.vram_data ( vram_do ),
|
||||
|
||||
// vram connection bank1 (GBC)
|
||||
.vram1_data ( vram1_do ),
|
||||
|
||||
.dma_rd ( dma_rd ),
|
||||
.dma_addr ( dma_addr ),
|
||||
.dma_data ( dma_data )
|
||||
|
||||
);
|
||||
|
||||
// total 8k vram from $8000 to $9fff
|
||||
// total 8k/16k (CGB) vram from $8000 to $9fff
|
||||
wire cpu_wr_vram = sel_vram && !cpu_wr_n;
|
||||
wire [7:0] vram_do;
|
||||
wire vram_wren = video_rd?1'b0:cpu_wr_vram;
|
||||
wire [12:0] vram_addr = video_rd?video_addr:cpu_addr[12:0];
|
||||
|
||||
vram vram (
|
||||
.clock ( clk ),
|
||||
.address ( vram_addr ),
|
||||
.wren ( vram_wren ),
|
||||
.data ( cpu_do ),
|
||||
.q ( vram_do )
|
||||
reg vram_bank; //0-1 FF4F - VBK
|
||||
|
||||
wire [7:0] vram_do,vram1_do;
|
||||
wire [7:0] vram_di = (hdma_rd&&isGBC)?
|
||||
hdma_sel_iram?iram_do:
|
||||
is_hdma_cart_addr?cart_do:
|
||||
8'hFF:
|
||||
cpu_do;
|
||||
|
||||
|
||||
wire vram_wren = video_rd?1'b0:!vram_bank&&((hdma_rd&&isGBC)||cpu_wr_vram);
|
||||
wire vram1_wren = video_rd?1'b0:vram_bank&&((hdma_rd&&isGBC)||cpu_wr_vram);
|
||||
|
||||
wire [12:0] vram_addr = video_rd?video_addr:(hdma_rd&&isGBC)?hdma_target_addr[12:0]:(dma_rd&&dma_sel_vram)?dma_addr[12:0]:cpu_addr[12:0];
|
||||
|
||||
|
||||
spram #(13) vram0 (
|
||||
.clock ( clk_cpu ),
|
||||
.address ( vram_addr ),
|
||||
.wren ( vram_wren ),
|
||||
.data ( vram_di ),
|
||||
.q ( vram_do )
|
||||
);
|
||||
|
||||
//separate 8k for vbank1 for gbc because of BG reads
|
||||
spram #(13) vram1 (
|
||||
.clock ( clk_cpu ),
|
||||
.address ( vram_addr ),
|
||||
.wren ( vram1_wren ),
|
||||
.data ( vram_di ),
|
||||
.q ( vram1_do )
|
||||
);
|
||||
|
||||
//GBC VRAM banking
|
||||
always @(posedge clk_cpu) begin
|
||||
if(reset)
|
||||
vram_bank <= 1'd0;
|
||||
else if((cpu_addr == 16'hff4f) && !cpu_wr_n && isGBC)
|
||||
vram_bank <= cpu_do[0];
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// -------------------------- HDMA engine(GBC) ------------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
wire [15:0] hdma_source_addr;
|
||||
wire [15:0] hdma_target_addr;
|
||||
wire [7:0] hdma_do;
|
||||
wire hdma_rd;
|
||||
|
||||
hdma hdma(
|
||||
.reset ( reset ),
|
||||
.clk ( clk2x ),
|
||||
|
||||
// cpu register interface
|
||||
.sel_reg ( sel_hdma ),
|
||||
.addr ( cpu_addr[3:0] ),
|
||||
.wr ( !cpu_wr_n ),
|
||||
.dout ( hdma_do ),
|
||||
.din ( cpu_do ),
|
||||
|
||||
.lcd_mode ( lcd_mode ),
|
||||
|
||||
// dma connection
|
||||
.hdma_rd ( hdma_rd ),
|
||||
.hdma_source_addr ( hdma_source_addr ),
|
||||
.hdma_target_addr ( hdma_target_addr )
|
||||
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -302,8 +481,8 @@ vram vram (
|
||||
// 127 bytes internal zero page ram from $ff80 to $fffe
|
||||
wire cpu_wr_zpram = sel_zpram && !cpu_wr_n;
|
||||
wire [7:0] zpram_do;
|
||||
zpram zpram (
|
||||
.clock ( clk ),
|
||||
spram #(7) zpram (
|
||||
.clock ( clk_cpu ),
|
||||
.address ( cpu_addr[6:0] ),
|
||||
.wren ( cpu_wr_zpram ),
|
||||
.data ( cpu_do ),
|
||||
@@ -311,49 +490,84 @@ zpram zpram (
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ------------------------- 8k internal ram --------------------------
|
||||
// ------------------------ 8k/32k(GBC) internal ram -----------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
wire iram_wren = dma_rd?1'b0:cpu_wr_iram;
|
||||
wire [12:0] iram_addr = dma_rd?dma_addr[12:0]:cpu_addr[12:0];
|
||||
reg [2:0] iram_bank; //1-7 FF70 - SVBK
|
||||
wire iram_wren = (dma_rd&&dma_sel_iram)||(isGBC&&hdma_rd&&hdma_sel_iram)?1'b0:cpu_wr_iram;
|
||||
|
||||
wire [14:0] iram_addr = (isGBC&&hdma_rd&&hdma_sel_iram)? //hdma transfer?
|
||||
(hdma_source_addr[12])?{iram_bank,hdma_source_addr[11:0]}: //bank 1-7 D000-DFFF
|
||||
{3'd0,hdma_source_addr[11:0]}: //bank 0
|
||||
(dma_rd&&dma_sel_iram)? //dma transfer?
|
||||
(dma_addr[12])?{iram_bank,dma_addr[11:0]}: //bank 1-7
|
||||
{3'd0,dma_addr[11:0]}: //bank 0
|
||||
//cpu
|
||||
(cpu_addr[12])?{iram_bank,cpu_addr[11:0]}: //bank 1-7
|
||||
{3'd0,cpu_addr[11:0]}; //bank 0
|
||||
|
||||
|
||||
wire cpu_wr_iram = sel_iram && !cpu_wr_n;
|
||||
wire [7:0] iram_do;
|
||||
iram iram (
|
||||
.clock ( clk ),
|
||||
.address ( iram_addr[12:0]),
|
||||
spram #(15) iram (
|
||||
.clock ( clk_cpu ),
|
||||
.address ( iram_addr ),
|
||||
.wren ( iram_wren ),
|
||||
.data ( cpu_do ),
|
||||
.q ( iram_do )
|
||||
);
|
||||
|
||||
//GBC WRAM banking
|
||||
always @(posedge clk_cpu) begin
|
||||
if(reset)
|
||||
iram_bank <= 3'd1;
|
||||
else if((cpu_addr == 16'hff70) && !cpu_wr_n && isGBC) begin
|
||||
if (cpu_do[2:0]==3'd0) // 0 -> 1;
|
||||
iram_bank <= 3'd1;
|
||||
else
|
||||
iram_bank <= cpu_do[2:0];
|
||||
end
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ------------------------ internal boot rom -------------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// writing 01 to $ff50 disables the internal rom
|
||||
// writing 01(GB) or 11(GBC) to $ff50 disables the internal rom
|
||||
reg boot_rom_enabled;
|
||||
always @(posedge clk) begin
|
||||
if(reset)
|
||||
boot_rom_enabled <= 1'b1;
|
||||
else if((cpu_addr == 16'hff50) && !cpu_wr_n && cpu_do[0])
|
||||
boot_rom_enabled <= 1'b0;
|
||||
else if((cpu_addr == 16'hff50) && !cpu_wr_n)
|
||||
if ((isGBC && cpu_do[7:0]==8'h11) || (!isGBC && cpu_do[0]))
|
||||
boot_rom_enabled <= 1'b0;
|
||||
end
|
||||
|
||||
// combine boot rom data with cartridge data
|
||||
wire [7:0] rom_do = ((cpu_addr[14:8] == 7'h00) && boot_rom_enabled)?boot_rom_do:cart_do;
|
||||
|
||||
wire [7:0] rom_do = isGBC? //GameBoy Color?
|
||||
(((cpu_addr[14:8] == 7'h00) || (hdma_rd&& hdma_source_addr[14:8] == 7'h00))&& boot_rom_enabled)?gbc_bios_do: //0-FF bootrom 1st part
|
||||
((cpu_addr[14:9] == 6'h00) || (hdma_rd&& hdma_source_addr[14:9] == 6'h00))? cart_do: //100-1FF Cart Header
|
||||
(((cpu_addr[14:12] == 3'h0) || (hdma_rd&& hdma_source_addr[14:12] == 3'h0)) && boot_rom_enabled)?gbc_bios_do: //200-8FF bootrom 2nd part
|
||||
cart_do: //rest of card
|
||||
((cpu_addr[14:8] == 7'h00) && boot_rom_enabled)?boot_rom_do:cart_do; //GB
|
||||
|
||||
|
||||
wire is_dma_cart_addr = (dma_sel_rom || dma_sel_cram); //rom or external ram
|
||||
wire is_hdma_cart_addr = (hdma_sel_rom || hdma_sel_cram); //rom or external ram
|
||||
|
||||
assign cart_di = cpu_do;
|
||||
assign cart_addr = dma_rd?dma_addr:cpu_addr;
|
||||
assign cart_rd = dma_rd || ((sel_rom || sel_cram) && !cpu_rd_n);
|
||||
assign cart_wr = (sel_rom || sel_cram) && !cpu_wr_n;
|
||||
assign cart_addr = (isGBC&&hdma_rd&&is_hdma_cart_addr)?hdma_source_addr:(dma_rd&&is_dma_cart_addr)?dma_addr:cpu_addr;
|
||||
assign cart_rd = (isGBC&&hdma_rd&&is_hdma_cart_addr) || (dma_rd&&is_dma_cart_addr) || ((sel_rom || sel_cram) && !cpu_rd_n);
|
||||
assign cart_wr = (sel_rom || sel_cram) && !cpu_wr_n && !hdma_rd;
|
||||
|
||||
assign gbc_bios_addr = hdma_rd?hdma_source_addr[11:0]:cpu_addr[11:0];
|
||||
|
||||
wire [7:0] boot_rom_do;
|
||||
boot_rom boot_rom (
|
||||
.address ( cpu_addr[7:0] ),
|
||||
.clock ( clk ),
|
||||
.q ( boot_rom_do )
|
||||
.address ( cpu_addr[7:0] ),
|
||||
.clock ( clk ),
|
||||
.q ( boot_rom_do )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -296,6 +296,7 @@ wire [15:0] audio_right;
|
||||
gb gb (
|
||||
.reset ( reset ),
|
||||
.clk ( clk4 ), // the whole gameboy runs on 4mhnz
|
||||
.clk2x ( clk8 ),
|
||||
|
||||
.fast_boot ( status[2] ),
|
||||
.joystick ( joystick ),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
331
cores/gameboy/hdma.v
Normal file
331
cores/gameboy/hdma.v
Normal file
@@ -0,0 +1,331 @@
|
||||
module hdma(
|
||||
input reset,
|
||||
input clk, // 8 Mhz cpu clock
|
||||
|
||||
// cpu register interface
|
||||
input sel_reg,
|
||||
input [3:0] addr,
|
||||
input wr,
|
||||
output [7:0] dout,
|
||||
input [7:0] din,
|
||||
|
||||
input [1:0] lcd_mode,
|
||||
|
||||
// dma connection
|
||||
output hdma_rd,
|
||||
output [15:0] hdma_source_addr,
|
||||
output [15:0] hdma_target_addr
|
||||
|
||||
);
|
||||
|
||||
//ff51-ff55 HDMA1-5 (GBC)
|
||||
reg [7:0] hdma_source_h; // ff51
|
||||
reg [3:0] hdma_source_l; // ff52 only top 4 bits used
|
||||
reg [4:0] hdma_target_h; // ff53 only lowest 5 bits used
|
||||
reg [3:0] hdma_target_l; // ff54 only top 4 bits used
|
||||
reg hdma_mode; // ff55 bit 7 - 1=General Purpose DMA 0=H-Blank DMA
|
||||
reg hdma_enabled; // ff55 !bit 7 when read
|
||||
reg [7:0] hdma_length; // ff55 bit 6:0 - dma transfer length (hdma_length+1)*16 bytes
|
||||
reg hdma_active;
|
||||
|
||||
// it takes about 8us to transfer a block of 16 bytes. -> 500ns per byte -> 2Mhz
|
||||
// 32 cycles in Normal Speed Mode, and 64 'fast' cycles in Double Speed Mode
|
||||
reg [13:0] hdma_cnt;
|
||||
reg [5:0] hdma_16byte_cnt; //16bytes*4
|
||||
|
||||
assign hdma_rd = hdma_active;
|
||||
assign hdma_source_addr = { hdma_source_h,hdma_source_l,4'd0} + hdma_cnt[13:2];
|
||||
assign hdma_target_addr = { 3'b100,hdma_target_h,hdma_target_l,4'd0} + hdma_cnt[13:2];
|
||||
|
||||
reg [1:0] hdma_state;
|
||||
parameter active=2'd0,blocksent=2'd1,wait_h=2'd2;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
hdma_active <= 1'b0;
|
||||
hdma_state <= wait_h;
|
||||
hdma_enabled <= 1'b0;
|
||||
hdma_source_h <= 8'hFF;
|
||||
hdma_source_l <= 4'hF;
|
||||
hdma_target_h <= 5'h1F;
|
||||
hdma_target_l <= 4'hF;
|
||||
end else begin
|
||||
if(sel_reg && wr) begin
|
||||
|
||||
case (addr)
|
||||
4'd1: hdma_source_h <= din;
|
||||
4'd2: hdma_source_l <= din[7:4];
|
||||
4'd3: hdma_target_h <= din[4:0];
|
||||
4'd4: hdma_target_l <= din[7:4];
|
||||
|
||||
|
||||
// writing the hdma register engages the dma engine
|
||||
4'h5: begin
|
||||
if (hdma_mode == 1 && hdma_enabled && !din[7]) begin //terminate an active H-Blank transfer by writing zero to Bit 7 of FF55
|
||||
hdma_state <= wait_h;
|
||||
hdma_active <= 1'b0;
|
||||
hdma_enabled <= 1'b0;
|
||||
end else begin //normal trigger
|
||||
hdma_enabled <= 1'b1;
|
||||
hdma_mode <= din[7];
|
||||
hdma_length <= {1'b0,din[6:0]} + 8'd1;
|
||||
hdma_cnt <= 14'd0;
|
||||
hdma_16byte_cnt <= 6'h3f;
|
||||
if (din[7] == 1) hdma_state <= wait_h;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (hdma_enabled) begin
|
||||
if(hdma_mode==0) begin //mode 0 GDMA do the transfer in one go
|
||||
if(hdma_length != 0) begin
|
||||
hdma_active <= 1'b1;
|
||||
hdma_cnt <= hdma_cnt + 1'd1;
|
||||
hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1;
|
||||
if (!hdma_16byte_cnt) begin
|
||||
hdma_length <= hdma_length - 1'd1;
|
||||
if (hdma_length == 1) begin
|
||||
hdma_active <= 1'b0;
|
||||
hdma_enabled <= 1'b0;
|
||||
hdma_length <= 8'h80; //7f+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end else begin //mode 1 HDMA transfer 1 block (16bytes) in each H-Blank only
|
||||
case (hdma_state)
|
||||
|
||||
wait_h: begin
|
||||
if (lcd_mode == 2'b00 ) // Mode 00: h-blank
|
||||
hdma_state <= active;
|
||||
hdma_16byte_cnt <= 6'h3f;
|
||||
hdma_active <= 1'b0;
|
||||
end
|
||||
|
||||
blocksent: begin
|
||||
if (hdma_length == 0) begin //check if finished
|
||||
hdma_enabled <= 1'b0;
|
||||
hdma_length <= 8'h80; //7f+1
|
||||
end
|
||||
if (lcd_mode == 2'b11) // wait for mode 3, mode before h-blank
|
||||
hdma_state <= wait_h;
|
||||
end
|
||||
|
||||
active: begin
|
||||
if(hdma_length != 0) begin
|
||||
hdma_active <= 1'b1;
|
||||
hdma_cnt <= hdma_cnt + 1'd1;
|
||||
hdma_16byte_cnt <= hdma_16byte_cnt - 1'd1;
|
||||
if (!hdma_16byte_cnt) begin
|
||||
hdma_length <= hdma_length - 1'd1;
|
||||
hdma_state <= blocksent;
|
||||
hdma_active <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
hdma_active <= 1'b0;
|
||||
hdma_enabled <= 1'b0;
|
||||
hdma_length <= 8'h80; //7f+1
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
wire [7:0] length_m1 = hdma_length - 8'd1;
|
||||
|
||||
assign dout = sel_reg?
|
||||
(addr==4'd5)?hdma_enabled?{1'b0,length_m1[6:0]}:
|
||||
{1'b1,length_m1[6:0]}:
|
||||
8'hFF:
|
||||
8'hFF;
|
||||
|
||||
endmodule
|
||||
|
||||
`timescale 1 ns/100 ps // time-unit = 1 ns, precision = 100 ps
|
||||
|
||||
module hdma_tb;
|
||||
|
||||
// duration for each bit = 125 * timescale = 125 * 1 ns = 125ns // 8MHz
|
||||
localparam period = 125;
|
||||
|
||||
reg reset = 1'd1;
|
||||
reg clk = 1'd0;
|
||||
|
||||
// cpu register interface
|
||||
reg sel_reg = 1'd0;
|
||||
reg [3:0] addr = 4'd0;
|
||||
reg wr = 1'd0;
|
||||
wire [7:0] dout;
|
||||
reg [7:0] din = 8'd0;
|
||||
|
||||
reg [1:0] lcd_mode = 2'd0;
|
||||
|
||||
// dma connection
|
||||
wire hdma_rd;
|
||||
wire [15:0] hdma_source_addr;
|
||||
wire [15:0] hdma_target_addr;
|
||||
|
||||
|
||||
|
||||
hdma hdma(
|
||||
.reset ( reset ),
|
||||
.clk ( clk ),
|
||||
|
||||
// cpu register interface
|
||||
.sel_reg ( sel_reg ),
|
||||
.addr ( addr ),
|
||||
.wr ( wr ),
|
||||
.dout ( dout ),
|
||||
.din ( din ),
|
||||
|
||||
.lcd_mode ( lcd_mode ),
|
||||
|
||||
// dma connection
|
||||
.hdma_rd ( hdma_rd ),
|
||||
.hdma_source_addr ( hdma_source_addr ),
|
||||
.hdma_target_addr ( hdma_target_addr )
|
||||
|
||||
);
|
||||
|
||||
always #62 clk <= !clk;
|
||||
initial begin
|
||||
reset <= 1'b0;
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd4;
|
||||
|
||||
#1000
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd1; // source h
|
||||
din <= 8'h20;
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#period
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd2; // source l
|
||||
din <= 8'h40;
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#period
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd3; // target h
|
||||
din <= 8'h82;
|
||||
wr <= 1'd1;
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#period
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd4; // target l
|
||||
din <= 8'h00;
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#period
|
||||
$display("GDMA");
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5; // trigger GDMA with length
|
||||
din <= 8'h01; // 20h bytes
|
||||
wr <= 1'd1;
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#8000
|
||||
|
||||
lcd_mode <= 2'd1;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd0;
|
||||
#8000
|
||||
|
||||
$display("HDMA");
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5; // trigger HDMA with length
|
||||
din <= 8'h82; // 30h bytes
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#16000
|
||||
|
||||
lcd_mode <= 2'd2;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd3;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd0;
|
||||
#16000
|
||||
|
||||
lcd_mode <= 2'd2;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd3;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd0;
|
||||
#16000
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5;
|
||||
$display("Check FF55");
|
||||
|
||||
#1000
|
||||
|
||||
$display("HDMA with cancel");
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5; // trigger HDMA with length
|
||||
din <= 8'h82; // 30h bytes
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#16000
|
||||
|
||||
lcd_mode <= 2'd2;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd3;
|
||||
#2000
|
||||
|
||||
$display("canceling");
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5; // trigger HDMA with length
|
||||
din <= 8'h00; // stop
|
||||
wr <= 1'd1;
|
||||
|
||||
#period
|
||||
wr <= 1'd0;
|
||||
|
||||
#16000
|
||||
|
||||
sel_reg <= 1'b1;
|
||||
addr <= 4'd5;
|
||||
$display("Check FF55");
|
||||
|
||||
lcd_mode <= 2'd2;
|
||||
#2000
|
||||
|
||||
lcd_mode <= 2'd3;
|
||||
#2000
|
||||
$display("Test Complete");
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,3 +0,0 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "iram.v"]
|
||||
@@ -1,172 +0,0 @@
|
||||
// megafunction wizard: %RAM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: iram.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module iram (
|
||||
address,
|
||||
clock,
|
||||
data,
|
||||
wren,
|
||||
q);
|
||||
|
||||
input [12:0] address;
|
||||
input clock;
|
||||
input [7:0] data;
|
||||
input wren;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.data_a (data),
|
||||
.wren_a (wren),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_a = "BYPASS",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 8192,
|
||||
altsyncram_component.operation_mode = "SINGLE_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "UNREGISTERED",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 13,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrData NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING ""
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegData NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "13"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
|
||||
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
|
||||
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL iram_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
55
cores/gameboy/spram.vhd
Normal file
55
cores/gameboy/spram.vhd
Normal file
@@ -0,0 +1,55 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.altera_mf_components.all;
|
||||
|
||||
ENTITY spram IS
|
||||
generic (
|
||||
addr_width : integer := 8;
|
||||
data_width : integer := 8
|
||||
);
|
||||
PORT
|
||||
(
|
||||
clock : IN STD_LOGIC;
|
||||
clken : IN STD_LOGIC := '1';
|
||||
address : IN STD_LOGIC_VECTOR (addr_width-1 DOWNTO 0);
|
||||
data : IN STD_LOGIC_VECTOR (data_width-1 DOWNTO 0);
|
||||
wren : IN STD_LOGIC := '0';
|
||||
q : OUT STD_LOGIC_VECTOR (data_width-1 DOWNTO 0)
|
||||
);
|
||||
END spram;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF spram IS
|
||||
|
||||
BEGIN
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
clock_enable_input_a => "NORMAL",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
intended_device_family => "Cyclone III",
|
||||
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**addr_width,
|
||||
operation_mode => "SINGLE_PORT",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_reg_a => "UNREGISTERED",
|
||||
power_up_uninitialized => "FALSE",
|
||||
read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ",
|
||||
widthad_a => addr_width,
|
||||
width_a => data_width,
|
||||
width_byteena_a => 1
|
||||
)
|
||||
PORT MAP (
|
||||
address_a => address,
|
||||
clock0 => clock,
|
||||
clocken0 => clken,
|
||||
data_a => data,
|
||||
wren_a => wren,
|
||||
q_a => q
|
||||
);
|
||||
|
||||
|
||||
|
||||
END SYN;
|
||||
@@ -32,12 +32,17 @@ module sprite (
|
||||
output [10:0] addr,
|
||||
input [1:0] ds,
|
||||
input [7:0] data,
|
||||
input [7:0] data_1,
|
||||
|
||||
output pixel_active,
|
||||
output pixel_cmap,
|
||||
output pixel_prio,
|
||||
output [1:0] pixel_data,
|
||||
|
||||
//gbc
|
||||
output [2:0] pixel_cmap_gbc,
|
||||
output tile_vbank,
|
||||
|
||||
input oam_wr,
|
||||
input [1:0] oam_addr,
|
||||
input [7:0] oam_di,
|
||||
@@ -53,8 +58,8 @@ reg [7:0] data0;
|
||||
reg [7:0] data1;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(ds[0]) data0 <= data;
|
||||
if(ds[1]) data1 <= data;
|
||||
if(ds[0]) data0 <= flags[3]?data_1:data;
|
||||
if(ds[1]) data1 <= flags[3]?data_1:data;
|
||||
end
|
||||
|
||||
wire [7:0] height = size16?8'd16:8'd8;
|
||||
@@ -63,15 +68,15 @@ wire v_visible = (v_cnt + 8'd16 >= y_pos) && (v_cnt + 8'd16 < y_pos + height);
|
||||
wire visible = v_visible && (h_cnt + 8'd8 >= x_pos) && (h_cnt < x_pos);
|
||||
|
||||
// x position within sprite, mirror horizontally if required
|
||||
wire [2:0] col_n = h_cnt - x_pos;
|
||||
wire [2:0] col = flags[1]?col_n:~col_n;
|
||||
wire [7:0] col_n = h_cnt - x_pos;
|
||||
wire [2:0] col = flags[5]?col_n[2:0]:~col_n[2:0];
|
||||
|
||||
assign pixel_data = { data1[col], data0[col] };
|
||||
assign pixel_active = (pixel_data != 0) && visible;
|
||||
|
||||
// y position within sprite, mirror vertically if required
|
||||
wire [3:0] row_n = v_cnt - y_pos;
|
||||
wire [3:0] row = flags[2]?~row_n:row_n;
|
||||
wire [7:0] row_n = v_cnt - y_pos;
|
||||
wire [3:0] row = flags[6]?~row_n[3:0]:row_n[3:0];
|
||||
|
||||
// 16 pixel tall sprites use one more rwo counter bit and the lsb
|
||||
// of the tile index is ignored
|
||||
@@ -79,13 +84,16 @@ wire [10:0] addr8 = { tile , row[2:0]};
|
||||
wire [10:0] addr16 = { tile[7:1] , row};
|
||||
assign addr = size16?addr16:addr8;
|
||||
|
||||
assign pixel_cmap = flags[0];
|
||||
assign pixel_prio = flags[3];
|
||||
assign pixel_cmap = flags[4];
|
||||
assign pixel_prio = flags[7];
|
||||
|
||||
assign pixel_cmap_gbc = flags[2:0];
|
||||
assign tile_vbank = flags[3];
|
||||
|
||||
reg [7:0] y_pos;
|
||||
reg [7:0] x_pos;
|
||||
reg [7:0] tile;
|
||||
reg [3:0] flags;
|
||||
reg [7:0] flags;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(oam_wr) begin
|
||||
@@ -93,7 +101,7 @@ always @(posedge clk) begin
|
||||
0: y_pos <= oam_di;
|
||||
1: x_pos <= oam_di;
|
||||
2: tile <= oam_di;
|
||||
3: flags <= oam_di[7:4];
|
||||
3: flags <= oam_di;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
@@ -102,6 +110,6 @@ assign oam_do =
|
||||
(oam_addr == 0)?y_pos:
|
||||
(oam_addr == 1)?x_pos:
|
||||
(oam_addr == 2)?tile:
|
||||
{ flags, 4'h0 };
|
||||
flags;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -87,7 +87,7 @@ generate
|
||||
always @(posedge clk) begin
|
||||
if(load) begin
|
||||
values[i] <= in[i];
|
||||
index[i] <= i;
|
||||
index[i] <= i[5:0];
|
||||
end else begin
|
||||
values[i] <= sort_val[i];
|
||||
index[i] <= sort_idx[i];
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
module sprites (
|
||||
input clk,
|
||||
input clk_reg,
|
||||
input size16,
|
||||
|
||||
// pixel position input which the current pixel is generated for
|
||||
@@ -33,11 +34,16 @@ module sprites (
|
||||
output pixel_cmap,
|
||||
output pixel_prio,
|
||||
|
||||
//gbc
|
||||
output [2:0] pixel_cmap_gbc,
|
||||
output tile_vbank,
|
||||
|
||||
input sort,
|
||||
input [3:0] index, // index of sprite which video wants to read data for
|
||||
output [10:0] addr,
|
||||
input [1:0] dvalid,
|
||||
input [7:0] data,
|
||||
input [7:0] data1,
|
||||
|
||||
// oam memory interface
|
||||
input oam_wr,
|
||||
@@ -79,6 +85,9 @@ wire [5:0] sprite_idx_array [SPRITES-1:0];
|
||||
wire [5:0] prio_index = sprite_idx_array[index];
|
||||
assign addr = sprite_addr[prio_index];
|
||||
|
||||
//gbc
|
||||
wire [2:0] sprite_pixel_cmap_gbc [SPRITES-1:0];
|
||||
wire sprite_tile_vbank [SPRITES-1:0];
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
@@ -87,7 +96,7 @@ for(i=0;i<SPRITES;i=i+1) begin : spr
|
||||
assign sprite_idx_array[i] = sprite_idx[6*i+5:6*i];
|
||||
|
||||
sprite sprite (
|
||||
.clk ( clk ),
|
||||
.clk ( clk_reg ),
|
||||
.size16 ( size16 ),
|
||||
|
||||
.v_cnt ( v_cnt ),
|
||||
@@ -97,11 +106,17 @@ for(i=0;i<SPRITES;i=i+1) begin : spr
|
||||
.addr ( sprite_addr[i] ),
|
||||
.ds ( (prio_index == i)?dvalid:2'b00),
|
||||
.data ( data ),
|
||||
.data_1 ( data1 ),
|
||||
|
||||
.pixel_cmap ( sprite_pixel_cmap[i] ),
|
||||
.pixel_prio ( sprite_pixel_prio[i] ),
|
||||
.pixel_active ( sprite_pixel_active[i] ),
|
||||
.pixel_data ( sprite_pixel_data[i] ),
|
||||
|
||||
|
||||
//gbc
|
||||
.pixel_cmap_gbc ( sprite_pixel_cmap_gbc[i] ),
|
||||
.tile_vbank ( sprite_tile_vbank[i] ),
|
||||
|
||||
.oam_wr ( oam_wr && (oam_addr[7:2] == i) ),
|
||||
.oam_addr ( oam_addr[1:0] ),
|
||||
@@ -171,6 +186,35 @@ assign pixel_cmap =
|
||||
sprite_pixel_active[spr9]?sprite_pixel_cmap[spr9]:
|
||||
1'b0;
|
||||
|
||||
// get the colormap of the leftmost sprite gbc
|
||||
assign pixel_cmap_gbc =
|
||||
sprite_pixel_active[spr0]?sprite_pixel_cmap_gbc[spr0]:
|
||||
sprite_pixel_active[spr1]?sprite_pixel_cmap_gbc[spr1]:
|
||||
sprite_pixel_active[spr2]?sprite_pixel_cmap_gbc[spr2]:
|
||||
sprite_pixel_active[spr3]?sprite_pixel_cmap_gbc[spr3]:
|
||||
sprite_pixel_active[spr4]?sprite_pixel_cmap_gbc[spr4]:
|
||||
sprite_pixel_active[spr5]?sprite_pixel_cmap_gbc[spr5]:
|
||||
sprite_pixel_active[spr6]?sprite_pixel_cmap_gbc[spr6]:
|
||||
sprite_pixel_active[spr7]?sprite_pixel_cmap_gbc[spr7]:
|
||||
sprite_pixel_active[spr8]?sprite_pixel_cmap_gbc[spr8]:
|
||||
sprite_pixel_active[spr9]?sprite_pixel_cmap_gbc[spr9]:
|
||||
1'b0;
|
||||
|
||||
// get the tile vbank of the leftmost sprite
|
||||
assign tile_vbank =
|
||||
sprite_pixel_active[spr0]?sprite_tile_vbank[spr0]:
|
||||
sprite_pixel_active[spr1]?sprite_tile_vbank[spr1]:
|
||||
sprite_pixel_active[spr2]?sprite_tile_vbank[spr2]:
|
||||
sprite_pixel_active[spr3]?sprite_tile_vbank[spr3]:
|
||||
sprite_pixel_active[spr4]?sprite_tile_vbank[spr4]:
|
||||
sprite_pixel_active[spr5]?sprite_tile_vbank[spr5]:
|
||||
sprite_pixel_active[spr6]?sprite_tile_vbank[spr6]:
|
||||
sprite_pixel_active[spr7]?sprite_tile_vbank[spr7]:
|
||||
sprite_pixel_active[spr8]?sprite_tile_vbank[spr8]:
|
||||
sprite_pixel_active[spr9]?sprite_tile_vbank[spr9]:
|
||||
1'b0;
|
||||
|
||||
|
||||
// get the priority of the leftmost sprite
|
||||
assign pixel_prio =
|
||||
sprite_pixel_active[spr0]?sprite_pixel_prio[spr0]:
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
module timer (
|
||||
input reset,
|
||||
input clk, // 4 Mhz cpu clock
|
||||
|
||||
output reg irq,
|
||||
|
||||
// cpu register interface
|
||||
@@ -45,9 +44,17 @@ module timer (
|
||||
// clk_div[8] = 8khz
|
||||
// clk_div[9] = 4khz
|
||||
|
||||
wire resetdiv = cpu_sel && cpu_wr && (cpu_addr == 2'b00); //resetdiv also resets internal counter
|
||||
|
||||
reg [9:0] clk_div;
|
||||
always @(posedge clk)
|
||||
clk_div <= clk_div + 10'd1;
|
||||
always @(posedge clk or posedge resetdiv)
|
||||
if(resetdiv)
|
||||
clk_div <= 10'd6;
|
||||
else
|
||||
if (reset)
|
||||
clk_div <= 10'd6;
|
||||
else
|
||||
clk_div <= clk_div + 10'd1;
|
||||
|
||||
reg [7:0] div;
|
||||
reg [7:0] tma;
|
||||
@@ -56,12 +63,13 @@ reg [2:0] tac;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
tima <= 8'h00;
|
||||
tma <= 8'h00;
|
||||
tac <= 8'h00;
|
||||
irq <= 1'b0;
|
||||
tima <= 0;
|
||||
tma <= 0;
|
||||
tac <= 0;
|
||||
irq <= 0;
|
||||
div <= 0;
|
||||
end else begin
|
||||
irq <= 1'b0;
|
||||
irq <= 0;
|
||||
|
||||
if(clk_div[7:0] == 0) // 16kHz
|
||||
div <= div + 8'd1;
|
||||
@@ -98,6 +106,6 @@ assign cpu_do =
|
||||
(cpu_addr == 2'b00)?div:
|
||||
(cpu_addr == 2'b01)?tima:
|
||||
(cpu_addr == 2'b10)?tma:
|
||||
{5'b00000, tac};
|
||||
{5'b11111, tac};
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
module video (
|
||||
input reset,
|
||||
input clk, // 4 Mhz cpu clock
|
||||
input clk_reg,
|
||||
input isGBC,
|
||||
|
||||
// cpu register adn oam interface
|
||||
input cpu_sel_oam,
|
||||
@@ -34,7 +36,7 @@ module video (
|
||||
// output to lcd
|
||||
output lcd_on,
|
||||
output lcd_clkena,
|
||||
output [1:0] lcd_data,
|
||||
output [14:0] lcd_data,
|
||||
output reg irq,
|
||||
|
||||
// vram connection
|
||||
@@ -42,6 +44,9 @@ module video (
|
||||
output vram_rd,
|
||||
output [12:0] vram_addr,
|
||||
input [7:0] vram_data,
|
||||
|
||||
// vram connection bank1 (GBC)
|
||||
input [7:0] vram1_data,
|
||||
|
||||
// dma connection
|
||||
output dma_rd,
|
||||
@@ -51,6 +56,7 @@ module video (
|
||||
|
||||
localparam STAGE2 = 9'd250; // oam + disp + pause
|
||||
localparam OAM_LEN = 80;
|
||||
localparam OAM_LEN16 = OAM_LEN/16;
|
||||
|
||||
wire sprite_pixel_active;
|
||||
wire [1:0] sprite_pixel_data;
|
||||
@@ -58,9 +64,13 @@ wire sprite_pixel_cmap;
|
||||
wire sprite_pixel_prio;
|
||||
|
||||
wire [7:0] oam_do;
|
||||
wire [3:0] sprite_index = h_cnt[7:4]-(OAM_LEN/16); // memory io starts at h_cnt == 16
|
||||
wire [3:0] sprite_index = h_cnt[7:4] - OAM_LEN16[3:0]; // memory io starts at h_cnt == 16
|
||||
wire [10:0] sprite_addr;
|
||||
|
||||
//gbc
|
||||
wire [2:0] sprite_pixel_cmap_gbc;
|
||||
wire sprite_tile_vbank;
|
||||
|
||||
// "data strobe" for the two bytes each sprite line consists of
|
||||
wire [1:0] sprite_dvalid = {
|
||||
(h_cnt[3:0] == 4'hf) && !vblank && !hblank,
|
||||
@@ -68,6 +78,7 @@ wire [1:0] sprite_dvalid = {
|
||||
|
||||
sprites sprites (
|
||||
.clk ( clk ),
|
||||
.clk_reg ( clk_reg ),
|
||||
.size16 ( lcdc_spr_siz ),
|
||||
|
||||
.v_cnt ( v_cnt ),
|
||||
@@ -79,10 +90,15 @@ sprites sprites (
|
||||
.pixel_cmap ( sprite_pixel_cmap ),
|
||||
.pixel_prio ( sprite_pixel_prio ),
|
||||
|
||||
.index ( sprite_index ),
|
||||
.addr ( sprite_addr ),
|
||||
.dvalid ( sprite_dvalid),
|
||||
.data ( vram_data ),
|
||||
.index ( sprite_index ),
|
||||
.addr ( sprite_addr ),
|
||||
.dvalid ( sprite_dvalid ),
|
||||
.data ( vram_data ),
|
||||
.data1 ( isGBC?vram1_data:vram_data ),
|
||||
|
||||
//gbc
|
||||
.pixel_cmap_gbc ( sprite_pixel_cmap_gbc ),
|
||||
.tile_vbank ( sprite_tile_vbank ),
|
||||
|
||||
.oam_wr ( oam_wr ),
|
||||
.oam_addr ( oam_addr ),
|
||||
@@ -119,7 +135,7 @@ reg [7:0] scx;
|
||||
reg [7:0] scx_r; // stable over line
|
||||
|
||||
// ff44 line counter
|
||||
reg [7:0] ly;
|
||||
wire [7:0] ly = v_cnt;
|
||||
|
||||
// ff45 line counter compare
|
||||
wire lyc_match = (ly == lyc);
|
||||
@@ -134,6 +150,22 @@ reg [7:0] wy_r; // stable over entire image
|
||||
reg [7:0] wx;
|
||||
reg [7:0] wx_r; // stable over line
|
||||
|
||||
|
||||
//ff68-ff6A GBC
|
||||
//FF68 - BCPS/BGPI - Background Palette Index
|
||||
reg [5:0] bgpi; //Bit 0-5 Index (00-3F)
|
||||
reg bgpi_ai; //Bit 7 Auto Increment (0=Disabled, 1=Increment after Writing)
|
||||
|
||||
//FF69 - BCPD/BGPD - Background Palette Data
|
||||
reg[7:0] bgpd [63:0]; //64 bytes
|
||||
|
||||
//FF6A - OCPS/OBPI - Sprite Palette Index
|
||||
reg [5:0] obpi; //Bit 0-5 Index (00-3F)
|
||||
reg obpi_ai; //Bit 7 Auto Increment (0=Disabled, 1=Increment after Writing)
|
||||
|
||||
//FF6B - OCPD/OBPD - Sprite Palette Data
|
||||
reg[7:0] obpd [63:0]; //64 bytes
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ----------------------------- DMA engine ---------------------------
|
||||
// --------------------------------------------------------------------
|
||||
@@ -144,12 +176,12 @@ assign dma_rd = dma_active;
|
||||
reg dma_active;
|
||||
reg [7:0] dma;
|
||||
reg [9:0] dma_cnt; // dma runs 4*160 clock cycles = 160us @ 4MHz
|
||||
always @(posedge clk) begin
|
||||
always @(posedge clk_reg) begin
|
||||
if(reset)
|
||||
dma_active <= 1'b0;
|
||||
else begin
|
||||
// writing the dma register engages the dma engine
|
||||
if(cpu_sel_reg && cpu_wr && (cpu_addr[3:0] == 4'h6)) begin
|
||||
if(cpu_sel_reg && cpu_wr && (cpu_addr == 8'h46)) begin
|
||||
dma_active <= 1'b1;
|
||||
dma_cnt <= 10'd0;
|
||||
end else if(dma_cnt != 160*4-1)
|
||||
@@ -163,11 +195,12 @@ end
|
||||
// ------------------------------- IRQs -------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
always @(posedge clk) begin
|
||||
always @(posedge clk_reg) begin //TODO: have to check if this is correct
|
||||
irq <= 1'b0;
|
||||
|
||||
|
||||
//TODO: investigate and fix timing of lyc=ly
|
||||
// lyc=ly coincidence
|
||||
if(stat[6] && (h_cnt == 0) && lyc_match)
|
||||
if(stat[6] && (h_cnt == 1) && lyc_match)
|
||||
irq <= 1'b1;
|
||||
|
||||
// begin of oam phase
|
||||
@@ -186,32 +219,65 @@ end
|
||||
// --------------------------------------------------------------------
|
||||
// --------------------- CPU register interface -----------------------
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
always @(posedge clk) begin
|
||||
integer ii=0;
|
||||
always @(posedge clk_reg) begin
|
||||
if(reset) begin
|
||||
lcdc <= 8'h00; // screen must be off since dmg rom writes to vram
|
||||
scy <= 8'h00;
|
||||
scx <= 8'h00;
|
||||
wy <= 8'h00;
|
||||
wx <= 8'h00;
|
||||
stat <= 8'h00;
|
||||
bgp <= 8'hfc;
|
||||
obp0 <= 8'hff;
|
||||
obp1 <= 8'hff;
|
||||
|
||||
bgpi <= 6'h0;
|
||||
obpi <= 6'h0;
|
||||
bgpi_ai <= 1'b0;
|
||||
obpi_ai <= 1'b0;
|
||||
|
||||
for (ii=0;ii<64;ii=ii+1)begin
|
||||
bgpd[ii] <= 8'h00;
|
||||
obpd[ii] <= 8'h00;
|
||||
end
|
||||
|
||||
end else begin
|
||||
if(cpu_sel_reg && cpu_wr) begin
|
||||
case(cpu_addr[3:0])
|
||||
4'h0: lcdc <= cpu_di;
|
||||
4'h1: stat <= cpu_di;
|
||||
4'h2: scy <= cpu_di;
|
||||
4'h3: scx <= cpu_di;
|
||||
case(cpu_addr)
|
||||
8'h40: lcdc <= cpu_di;
|
||||
8'h41: stat <= cpu_di;
|
||||
8'h42: scy <= cpu_di;
|
||||
8'h43: scx <= cpu_di;
|
||||
// a write to 4 is supposed to reset the v_cnt
|
||||
4'h5: lyc <= cpu_di;
|
||||
4'h6: dma <= cpu_di;
|
||||
4'h7: bgp <= cpu_di;
|
||||
4'h8: obp0 <= cpu_di;
|
||||
4'h9: obp1 <= cpu_di;
|
||||
4'ha: wy <= cpu_di;
|
||||
4'hb: wx <= cpu_di;
|
||||
8'h45: lyc <= cpu_di;
|
||||
8'h46: dma <= cpu_di;
|
||||
8'h47: bgp <= cpu_di;
|
||||
8'h48: obp0 <= cpu_di;
|
||||
8'h49: obp1 <= cpu_di;
|
||||
8'h4a: wy <= cpu_di;
|
||||
8'h4b: wx <= cpu_di;
|
||||
|
||||
//gbc
|
||||
8'h68: begin
|
||||
bgpi <= cpu_di[5:0];
|
||||
bgpi_ai <= cpu_di[7];
|
||||
end
|
||||
8'h69: begin
|
||||
bgpd[bgpi] <= cpu_di;
|
||||
if (bgpi_ai)
|
||||
bgpi <= bgpi + 6'h1;
|
||||
end
|
||||
8'h6A: begin
|
||||
obpi <= cpu_di[5:0];
|
||||
obpi_ai <= cpu_di[7];
|
||||
end
|
||||
8'h6B: begin
|
||||
obpd[obpi] <= cpu_di;
|
||||
if (obpi_ai)
|
||||
obpi <= obpi + 6'h1;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
@@ -219,18 +285,24 @@ end
|
||||
|
||||
assign cpu_do =
|
||||
cpu_sel_oam?oam_do:
|
||||
(cpu_addr[3:0] == 4'h0)?lcdc:
|
||||
(cpu_addr[3:0] == 4'h1)?{stat[7:3], lyc_match, mode}:
|
||||
(cpu_addr[3:0] == 4'h2)?scy:
|
||||
(cpu_addr[3:0] == 4'h3)?scx:
|
||||
(cpu_addr[3:0] == 4'h4)?ly:
|
||||
(cpu_addr[3:0] == 4'h5)?lyc:
|
||||
(cpu_addr[3:0] == 4'h6)?dma:
|
||||
(cpu_addr[3:0] == 4'h7)?bgp:
|
||||
(cpu_addr[3:0] == 4'h8)?obp0:
|
||||
(cpu_addr[3:0] == 4'h9)?obp1:
|
||||
(cpu_addr[3:0] == 4'ha)?wy:
|
||||
(cpu_addr[3:0] == 4'hb)?wx:
|
||||
(cpu_addr == 8'h40)?lcdc:
|
||||
(cpu_addr == 8'h41)?{1'b1,stat[6:3], lyc_match, mode}:
|
||||
(cpu_addr == 8'h42)?scy:
|
||||
(cpu_addr == 8'h43)?scx:
|
||||
(cpu_addr == 8'h44)?ly:
|
||||
(cpu_addr == 8'h45)?lyc:
|
||||
(cpu_addr == 8'h46)?dma:
|
||||
(cpu_addr == 8'h47)?bgp:
|
||||
(cpu_addr == 8'h48)?obp0:
|
||||
(cpu_addr == 8'h49)?obp1:
|
||||
(cpu_addr == 8'h4a)?wy:
|
||||
(cpu_addr == 8'h4b)?wx:
|
||||
isGBC?
|
||||
(cpu_addr == 8'h68)?{bgpi_ai,1'd0,bgpi}:
|
||||
(cpu_addr == 8'h69)?bgpd[bgpi]:
|
||||
(cpu_addr == 8'h6a)?{obpi_ai,1'd0,obpi}:
|
||||
(cpu_addr == 8'h6b)?obpd[obpi]:
|
||||
8'hff:
|
||||
8'hff;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -240,36 +312,51 @@ assign cpu_do =
|
||||
assign lcd_data = stage2_data;
|
||||
assign lcd_clkena = stage2_clkena;
|
||||
|
||||
reg [1:0] stage2_data;
|
||||
reg [14:0] stage2_data;
|
||||
reg stage2_clkena;
|
||||
|
||||
reg [1:0] stage2_buffer [159:0];
|
||||
reg [3:0] stage2_bgp_buffer_pix [159:0]; //GBC keep record of palette used for tile and priority
|
||||
|
||||
reg [7:0] stage2_wptr;
|
||||
reg [7:0] stage2_rptr;
|
||||
|
||||
// apply bg palette
|
||||
wire [1:0] stage2_bg_pix = (!lcdc_bg_ena && !window_ena)?2'b11: // background off?
|
||||
(stage2_buffer[stage2_rptr] == 2'b00)?bgp[1:0]:
|
||||
(stage2_buffer[stage2_rptr] == 2'b01)?bgp[3:2]:
|
||||
(stage2_buffer[stage2_rptr] == 2'b10)?bgp[5:4]:
|
||||
bgp[7:6];
|
||||
|
||||
wire [5:0] palette_index = (stage2_bgp_buffer_pix[stage2_rptr][2:0] << 3) + (stage2_buffer[stage2_rptr]<<1); //gbc
|
||||
|
||||
|
||||
// apply bg palette
|
||||
wire [14:0] stage2_bg_pix = (!lcdc_bg_ena && !window_ena)?15'h7FFF: // background off?
|
||||
isGBC?{bgpd[palette_index+1][6:0],bgpd[palette_index]}: //gbc
|
||||
(stage2_buffer[stage2_rptr] == 2'b00)?{13'd0,bgp[1:0]}:
|
||||
(stage2_buffer[stage2_rptr] == 2'b01)?{13'd0,bgp[3:2]}:
|
||||
(stage2_buffer[stage2_rptr] == 2'b10)?{13'd0,bgp[5:4]}:
|
||||
{13'd0,bgp[7:6]};
|
||||
|
||||
|
||||
|
||||
// apply sprite palette
|
||||
|
||||
wire [5:0] sprite_palette_index = (sprite_pixel_cmap_gbc << 3) + (sprite_pixel_data<<1); //gbc
|
||||
|
||||
wire [7:0] obp = sprite_pixel_cmap?obp1:obp0;
|
||||
wire [1:0] sprite_pix =
|
||||
(sprite_pixel_data == 2'b00)?obp[1:0]:
|
||||
(sprite_pixel_data == 2'b01)?obp[3:2]:
|
||||
(sprite_pixel_data == 2'b10)?obp[5:4]:
|
||||
obp[7:6];
|
||||
wire [14:0] sprite_pix = isGBC?{obpd[sprite_palette_index+1][6:0],obpd[sprite_palette_index]}: //gbc
|
||||
(sprite_pixel_data == 2'b00)?{13'd0,obp[1:0]}:
|
||||
(sprite_pixel_data == 2'b01)?{13'd0,obp[3:2]}:
|
||||
(sprite_pixel_data == 2'b10)?{13'd0,obp[5:4]}:
|
||||
{13'd0,obp[7:6]};
|
||||
|
||||
// a sprite pixel is visible if
|
||||
// - sprites are enabled
|
||||
// - there's a sprite at the current position
|
||||
// - the sprites prioroty bit is 0, or
|
||||
// - the prites priority is 1 and the backrgound color is 00
|
||||
// - the sprites priority is 1 and the backrgound color is 00
|
||||
// - GBC : BG priority is 0
|
||||
|
||||
wire bg_piority = isGBC&&stage2_bgp_buffer_pix[stage2_rptr][3];
|
||||
|
||||
wire sprite_pixel_visible =
|
||||
sprite_pixel_active && lcdc_spr_ena &&
|
||||
sprite_pixel_active && lcdc_spr_ena && (~bg_piority) &&
|
||||
((!sprite_pixel_prio) || (stage2_buffer[stage2_rptr] == 2'b00));
|
||||
|
||||
always @(posedge clk) begin
|
||||
@@ -280,6 +367,7 @@ always @(posedge clk) begin
|
||||
|
||||
if(stage1_clkena) begin
|
||||
stage2_buffer[stage2_wptr] <= stage1_data;
|
||||
stage2_bgp_buffer_pix[stage2_wptr] <= {bg_tile_attr_old[7],bg_tile_attr_old[2:0]}; //GBC: buffer palette and Priority Bit
|
||||
stage2_wptr <= stage2_wptr + 8'd1;
|
||||
end
|
||||
|
||||
@@ -289,7 +377,7 @@ always @(posedge clk) begin
|
||||
if(sprite_pixel_visible) stage2_data <= sprite_pix;
|
||||
else stage2_data <= stage2_bg_pix;
|
||||
|
||||
stage2_rptr <= stage2_rptr + 8'd1;
|
||||
stage2_rptr <= stage2_rptr + 8'd1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -303,31 +391,53 @@ reg window_ena;
|
||||
reg [7:0] tile_shift_0;
|
||||
reg [7:0] tile_shift_1;
|
||||
|
||||
reg [7:0] tile_shift_0_x;
|
||||
reg [7:0] tile_shift_1_x;
|
||||
|
||||
|
||||
reg [7:0] bg_tile;
|
||||
reg [7:0] bg_tile_data0;
|
||||
reg [7:0] bg_tile_data1;
|
||||
|
||||
|
||||
wire stage1_clkena = !vblank && hdvalid;
|
||||
wire [1:0] stage1_data = { tile_shift_1[7], tile_shift_0[7] };
|
||||
wire [1:0] stage1_data = (isGBC&&bg_tile_attr_old[5])?{ tile_shift_1_x[0], tile_shift_0_x[0] }:{ tile_shift_1[7], tile_shift_0[7] };
|
||||
|
||||
wire [7:0] vram_gbc_data = bg_tile_attr_new[3]?vram1_data:vram_data; //gbc check tile bank
|
||||
reg [7:0] bg_tile_attr_old,bg_tile_attr_new; //GBC
|
||||
|
||||
// read data half a clock cycle after ram has been selected
|
||||
always @(posedge clk) begin
|
||||
|
||||
|
||||
// every memory access is two pixel cycles
|
||||
if(h_cnt[0]) begin
|
||||
if(bg_tile_map_rd) bg_tile <= vram_data;
|
||||
if(bg_tile_data0_rd) bg_tile_data0 <= vram_data;
|
||||
if(bg_tile_data1_rd) bg_tile_data1 <= vram_data;
|
||||
|
||||
if (isGBC) begin
|
||||
if(bg_tile_map_rd) bg_tile_attr_new <= vram1_data; //get tile attr from vram bank1
|
||||
if(bg_tile_data0_rd) bg_tile_data0 <= vram_gbc_data;
|
||||
if(bg_tile_data1_rd) bg_tile_data1 <= vram_gbc_data;
|
||||
end else begin
|
||||
if(bg_tile_data0_rd) bg_tile_data0 <= vram_data;
|
||||
if(bg_tile_data1_rd) bg_tile_data1 <= vram_data;
|
||||
end
|
||||
|
||||
// sprite data is evaluated inside the sprite engine
|
||||
end
|
||||
|
||||
// shift bg/window pixels out
|
||||
if(bg_tile_obj_rd && h_cnt[0]) begin
|
||||
bg_tile_attr_old <= bg_tile_attr_new;
|
||||
tile_shift_0 <= bg_tile_data0;
|
||||
tile_shift_1 <= bg_tile_data1;
|
||||
end else begin
|
||||
tile_shift_0_x <= bg_tile_data0;
|
||||
tile_shift_1_x <= bg_tile_data1;
|
||||
end else begin
|
||||
tile_shift_0 <= { tile_shift_0[6:0], 1'b0 };
|
||||
tile_shift_1 <= { tile_shift_1[6:0], 1'b0 };
|
||||
//GBC x-flip
|
||||
tile_shift_0_x <= { 1'b0,tile_shift_0_x[7:1]};
|
||||
tile_shift_1_x <= { 1'b0,tile_shift_1_x[7:1]};
|
||||
end
|
||||
end
|
||||
|
||||
@@ -338,10 +448,12 @@ wire bg_tile_a12 = !lcdc_tile_data_sel?(~bg_tile[7]):1'b0;
|
||||
|
||||
wire tile_map_sel = window_ena?lcdc_win_tile_map_sel:lcdc_bg_tile_map_sel;
|
||||
|
||||
wire [2:0] tile_line_gbc = bg_tile_attr_new[6]? (3'b111 - tile_line): tile_line; //GBC: check if flipped y
|
||||
|
||||
assign vram_addr =
|
||||
bg_tile_map_rd?{2'b11, tile_map_sel, bg_tile_map_addr}:
|
||||
bg_tile_data0_rd?{bg_tile_a12, bg_tile, tile_line, 1'b0}:
|
||||
bg_tile_data1_rd?{bg_tile_a12, bg_tile, tile_line, 1'b1}:
|
||||
bg_tile_data0_rd?{bg_tile_a12, bg_tile, isGBC?tile_line_gbc:tile_line, 1'b0}:
|
||||
bg_tile_data1_rd?{bg_tile_a12, bg_tile, isGBC?tile_line_gbc:tile_line, 1'b1}:
|
||||
{1'b0, sprite_addr, h_cnt[3]};
|
||||
|
||||
reg [9:0] bg_tile_map_addr;
|
||||
@@ -434,6 +546,7 @@ wire bg_tile_obj_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b11);
|
||||
// Mode 10: oam
|
||||
// Mode 11: oam and vram
|
||||
assign mode =
|
||||
!lcdc_on?2'b00:
|
||||
vblank?2'b01:
|
||||
oam?2'b10:
|
||||
hblank?2'b00:
|
||||
@@ -449,63 +562,70 @@ wire [2:0] tile_line = window_ena?win_line[2:0]:bg_line[2:0];
|
||||
|
||||
wire win_start = lcdc_win_ena && (v_cnt >= wy_r) && de && (wx_r >= 7) && (pcnt == wx_r-8);
|
||||
|
||||
|
||||
|
||||
// each memory access takes two cycles
|
||||
always @(negedge clk) begin
|
||||
// this ly change h_cnt is wrong!!!
|
||||
if(h_cnt == 0)
|
||||
ly <= (v_cnt >= 153)?(v_cnt-8'd153):(v_cnt+8'd1);
|
||||
always @(negedge clk or negedge lcdc_on) begin
|
||||
|
||||
if(h_cnt != 455) begin
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
|
||||
// make sure sginals don't change during the line
|
||||
// latch at latest possible moment (one clock before display starts)
|
||||
if(h_cnt == OAM_LEN-2) begin
|
||||
scx_r <= scx;
|
||||
wx_r <= wx;
|
||||
scy_r <= scy;
|
||||
end
|
||||
|
||||
// increment address at the end of each 8-pixel-cycle. But don't
|
||||
// increment while waiting for current cycle to end due to window start
|
||||
if(!hblank && h_cnt[2:0] == 3'b111 && (skip <= 8))
|
||||
bg_tile_map_addr[4:0] <= bg_tile_map_addr[4:0] + 10'd1;
|
||||
|
||||
// begin of line
|
||||
if(h_cnt == OAM_LEN-1) begin
|
||||
// set tile map address for this line, assume there is no window
|
||||
bg_tile_map_addr[9:5] <= bg_line[7:3];
|
||||
bg_tile_map_addr[4:0] <= scx_r[7:3];
|
||||
if (!lcdc_on) begin // don't increase counters if lcdoff
|
||||
//reset counters
|
||||
h_cnt <= 9'd0;
|
||||
v_cnt <= 8'd0;
|
||||
|
||||
// special case wx < 8: line starts with window, no background
|
||||
// visible at all
|
||||
if(lcdc_win_ena && (v_cnt >= wy_r) && (wx_r < 8)) begin
|
||||
end else begin
|
||||
|
||||
if(h_cnt != 455) begin
|
||||
h_cnt <= h_cnt + 9'd1;
|
||||
|
||||
// make sure sginals don't change during the line
|
||||
// latch at latest possible moment (one clock before display starts)
|
||||
if(h_cnt == OAM_LEN-2) begin
|
||||
scx_r <= scx;
|
||||
wx_r <= wx;
|
||||
scy_r <= scy;
|
||||
end
|
||||
|
||||
// increment address at the end of each 8-pixel-cycle. But don't
|
||||
// increment while waiting for current cycle to end due to window start
|
||||
if(!hblank && h_cnt[2:0] == 3'b111 && (skip <= 8))
|
||||
bg_tile_map_addr[4:0] <= bg_tile_map_addr[4:0] + 1'd1;
|
||||
|
||||
// begin of line
|
||||
if(h_cnt == OAM_LEN-1) begin
|
||||
// set tile map address for this line, assume there is no window
|
||||
bg_tile_map_addr[9:5] <= bg_line[7:3];
|
||||
bg_tile_map_addr[4:0] <= scx_r[7:3];
|
||||
|
||||
// special case wx < 8: line starts with window, no background
|
||||
// visible at all
|
||||
if(lcdc_win_ena && (v_cnt >= wy_r) && (wx_r < 8)) begin
|
||||
window_ena <= 1'b1;
|
||||
bg_tile_map_addr[9:5] <= win_line[7:3];
|
||||
bg_tile_map_addr[4:0] <= 5'd0; // window always start with its very left
|
||||
end
|
||||
end
|
||||
|
||||
// check if the window starts here
|
||||
if(win_start) begin
|
||||
window_ena <= 1'b1;
|
||||
bg_tile_map_addr[9:5] <= win_line[7:3];
|
||||
bg_tile_map_addr[4:0] <= 5'd0; // window always start with its very left
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
window_ena <= 1'b0; // next line starts with background
|
||||
|
||||
// check if the window starts here
|
||||
if(win_start) begin
|
||||
window_ena <= 1'b1;
|
||||
bg_tile_map_addr[9:5] <= win_line[7:3];
|
||||
bg_tile_map_addr[4:0] <= 5'd0; // window always start with its very left
|
||||
end
|
||||
end else begin
|
||||
window_ena <= 1'b0; // next line starts with background
|
||||
|
||||
// end of line reached
|
||||
h_cnt <= 9'd0;
|
||||
|
||||
if(v_cnt != 153)
|
||||
v_cnt <= v_cnt + 8'd1;
|
||||
else begin
|
||||
// start of new image
|
||||
v_cnt <= 8'd0;
|
||||
|
||||
// make sure sginals don't change during the image
|
||||
wy_r <= wy;
|
||||
// end of line reached
|
||||
h_cnt <= 9'd0;
|
||||
|
||||
if(v_cnt != 153)
|
||||
v_cnt <= v_cnt + 8'd1;
|
||||
else begin
|
||||
// start of new image
|
||||
v_cnt <= 8'd0;
|
||||
|
||||
// make sure sginals don't change during the image
|
||||
wy_r <= wy;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "vram.v"]
|
||||
@@ -1,172 +0,0 @@
|
||||
// megafunction wizard: %RAM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: vram.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module vram (
|
||||
address,
|
||||
clock,
|
||||
data,
|
||||
wren,
|
||||
q);
|
||||
|
||||
input [12:0] address;
|
||||
input clock;
|
||||
input [7:0] data;
|
||||
input wren;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.data_a (data),
|
||||
.wren_a (wren),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_a = "BYPASS",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 8192,
|
||||
altsyncram_component.operation_mode = "SINGLE_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "UNREGISTERED",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 13,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrData NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING ""
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegData NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "13"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
|
||||
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
|
||||
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL vram_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
@@ -1,3 +0,0 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "zpram.v"]
|
||||
@@ -1,172 +0,0 @@
|
||||
// megafunction wizard: %RAM: 1-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: zpram.v
|
||||
// Megafunction Name(s):
|
||||
// altsyncram
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module zpram (
|
||||
address,
|
||||
clock,
|
||||
data,
|
||||
wren,
|
||||
q);
|
||||
|
||||
input [7:0] address;
|
||||
input clock;
|
||||
input [7:0] data;
|
||||
input wren;
|
||||
output [7:0] q;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_off
|
||||
`endif
|
||||
tri1 clock;
|
||||
`ifndef ALTERA_RESERVED_QIS
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
wire [7:0] sub_wire0;
|
||||
wire [7:0] q = sub_wire0[7:0];
|
||||
|
||||
altsyncram altsyncram_component (
|
||||
.address_a (address),
|
||||
.clock0 (clock),
|
||||
.data_a (data),
|
||||
.wren_a (wren),
|
||||
.q_a (sub_wire0),
|
||||
.aclr0 (1'b0),
|
||||
.aclr1 (1'b0),
|
||||
.address_b (1'b1),
|
||||
.addressstall_a (1'b0),
|
||||
.addressstall_b (1'b0),
|
||||
.byteena_a (1'b1),
|
||||
.byteena_b (1'b1),
|
||||
.clock1 (1'b1),
|
||||
.clocken0 (1'b1),
|
||||
.clocken1 (1'b1),
|
||||
.clocken2 (1'b1),
|
||||
.clocken3 (1'b1),
|
||||
.data_b (1'b1),
|
||||
.eccstatus (),
|
||||
.q_b (),
|
||||
.rden_a (1'b1),
|
||||
.rden_b (1'b1),
|
||||
.wren_b (1'b0));
|
||||
defparam
|
||||
altsyncram_component.clock_enable_input_a = "BYPASS",
|
||||
altsyncram_component.clock_enable_output_a = "BYPASS",
|
||||
altsyncram_component.intended_device_family = "Cyclone III",
|
||||
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
|
||||
altsyncram_component.lpm_type = "altsyncram",
|
||||
altsyncram_component.numwords_a = 256,
|
||||
altsyncram_component.operation_mode = "SINGLE_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "UNREGISTERED",
|
||||
altsyncram_component.power_up_uninitialized = "FALSE",
|
||||
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 8,
|
||||
altsyncram_component.width_a = 8,
|
||||
altsyncram_component.width_byteena_a = 1;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrByte NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrData NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clken NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
|
||||
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
|
||||
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MIFfilename STRING ""
|
||||
// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "256"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: RegAddr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegData NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: RegOutput NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: SingleClock NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: WidthAddr NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WidthData NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: rden NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
|
||||
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
|
||||
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
|
||||
// Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL "address[7..0]"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
|
||||
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren"
|
||||
// Retrieval info: CONNECT: @address_a 0 0 8 0 address 0 0 8 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
|
||||
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
Reference in New Issue
Block a user