Project

General

Profile

« Previous | Next » 

Revision 39

Added by markw over 11 years ago

No need for mmu to deal with refresh at all

View differences:

common/a8core/address_decoder.vhdl
ANTIC_ADDR : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
ANTIC_FETCH : IN STD_LOGIC;
antic_refresh : in std_logic; -- use for sdram refresh (sdram needs more, but this is a start)
DMA_ADDR : in std_logic_vector(23 downto 0);
DMA_FETCH : in std_logic;
......
SDRAM_WRITE_EN : out std_logic;
--SDRAM_REQUEST : out std_logic; -- Toggle this to issue a new request
SDRAM_REQUEST : out std_logic; -- Usual pattern
SDRAM_REFRESH : out std_logic;
--SDRAM_REPLY : in std_logic; -- This matches the request once complete
SDRAM_REQUEST_COMPLETE : in std_logic;
......
SDRAM_REQUEST <= sdram_chip_select;
--SDRAM_REQUEST <= sdram_request_next;
SDRAM_REFRESH <= '0'; --fetch_wait_reg(7); -- TODO, BROKEN! antic_refresh;
SDRAM_READ_EN <= not(write_enable_next);
SDRAM_WRITE_EN <= write_enable_next;
common/a8core/antic.vhdl
END antic;
ARCHITECTURE vhdl OF antic IS
component enable_divider IS
generic(COUNT : natural := 1);
PORT
(
CLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
ENABLE_IN : IN STD_LOGIC;
ENABLE_OUT : OUT STD_LOGIC
);
END component;
COMPONENT complete_address_decoder IS
generic (width : natural := 1);
PORT
......
-- Colour clock (3.57MHz for PAL)
-- TODO - allow double for 640 pixel width and quadruple for 1280 pixel width)
-- TODO - allow other clocks for driving VGA (mostly higher dot clock + line doubling (buffer between antic and gtia??))
--enable_colour_clock_div : enable_divider
--generic map (COUNT=>7)
--port map(clk=>clk,reset_n=>reset_n,enable_in=>'1',enable_out=>enable_colour_clock);
colour_clock_count_reg_topthree <= colour_clock_count_reg(cycle_length_bits-1 downto cycle_length_bits-3);
process(colour_clock_count_reg, colour_clock_count_reg_topthree, ANTIC_ENABLE_179)
......
end case;
end process;
--enable_dma_clock_div : enable_divider
-- generic map (COUNT=>2)
-- port map(clk=>clk,reset_n=>reset_n,enable_in=>colour_clock_selected,enable_out=>enable_dma);
-- Counters (memory address for data, memory address for display list)
antic_counter_memory_scan : antic_counter
generic map (STORE_WIDTH=>16, COUNT_WIDTH=>12)
......
begin
increment_refresh_count <= '0';
refresh_pending_next <= refresh_pending_reg;
refresh_fetch_next <= not(memory_ready_antic) and refresh_fetch_reg;
refresh_fetch_next <= '0';
if (colour_clock_1x = '1') then
-- do pending refresh once we have a spare cycle
......
-- wsync write takes 1 cycle to assert rdy
-- TODO - revisit antic delays in terms of cpu cycles
wsync_delay : delay_line
generic map (COUNT=>cycle_length+cycle_length/2)
--generic map (COUNT=>cycle_length+cycle_length/2)
generic map (COUNT=>cycle_length+cycle_length-2) -- TODO
port map (clk=>clk,sync_reset=>'0',data_in=>wsync_write,enable=>'1',reset_n=>reset_n,data_out=>wsync_delayed_write);
-- dmactl takes 1 cycle to be applied - NO IT DOES NOT - TODO FIXME
......
antic_ready <= not(wsync_reg);
dma_fetch_out <= refresh_fetch_reg or (allow_real_dma_reg and dma_fetch_reg);
dma_fetch_out <= allow_real_dma_reg and dma_fetch_reg;
dma_address_out <= dma_address_reg;
refresh_out <= refresh_fetch_reg;
common/a8core/atari800core.vhd
(
cycle_length : integer := 16; -- or 32...
video_bits : integer := 8;
palette : integer :=1 -- 0:gtia colour on VGA_B, 1:altirra, 2:laoo
palette : integer :=1 -- 0:gtia colour on VIDEO_B, 1:altirra, 2:laoo
);
PORT
(
......
RESET_N : IN STD_LOGIC;
-- VIDEO OUT - PAL/NTSC, original Atari timings approx (may be higher res)
VGA_VS : OUT STD_LOGIC;
VGA_HS : OUT STD_LOGIC;
VGA_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_VS : OUT STD_LOGIC;
VIDEO_HS : OUT STD_LOGIC;
VIDEO_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_BLANK : out std_logic;
VIDEO_BURST : out std_logic;
VIDEO_START_OF_FIELD : out std_logic;
VIDEO_ODD_LINE : out std_logic;
-- AUDIO OUT - Pokey/GTIA 1-bit and Covox all mixed
-- TODO - choose stereo/mono pokey
......
-- ANTIC lightpen
ANTIC_LIGHTPEN : IN std_logic;
ANTIC_REFRESH : out STD_LOGIC; -- 1 cycle high when antic doing refresh cycle..., propose locking out for the next 'cycle_length'
-----------------------
-- After here all FPGA implementation specific
......
SDRAM_ADDR : out STD_LOGIC_VECTOR(22 DOWNTO 0);
SDRAM_DO : in STD_LOGIC_VECTOR(31 DOWNTO 0);
-- ANTIC refresh cycles
-- TODO, expose a better way...
SDRAM_REFRESH : out STD_LOGIC;
RAM_ADDR : OUT STD_LOGIC_VECTOR(18 DOWNTO 0);
RAM_DO : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
RAM_REQUEST : OUT STD_LOGIC;
......
SIGNAL ANTIC_HIGHRES_COLOUR_CLOCK_OUT : STD_LOGIC;
SIGNAL ANTIC_ORIGINAL_COLOUR_CLOCK_OUT : STD_LOGIC;
SIGNAL ANTIC_RDY : STD_LOGIC;
SIGNAL ANTIC_REFRESH : STD_LOGIC;
SIGNAL ANTIC_WRITE_ENABLE : STD_LOGIC;
SIGNAL BREAK_PRESSED : STD_LOGIC;
signal hcount_temp : std_logic_vector(7 downto 0);
signal vcount_temp : std_logic_vector(8 downto 0);
signal ANTIC_REFRESH_CYCLE : STD_LOGIC;
-- GTIA
SIGNAL GTIA_SOUND : STD_LOGIC;
......
signal COLOUR : std_logic_vector(7 downto 0);
-- GTIA PALETTE
signal VGA_R_WIDE : std_logic_vector(7 downto 0);
signal VGA_G_WIDE : std_logic_vector(7 downto 0);
signal VGA_B_WIDE : std_logic_vector(7 downto 0);
signal VIDEO_R_WIDE : std_logic_vector(7 downto 0);
signal VIDEO_G_WIDE : std_logic_vector(7 downto 0);
signal VIDEO_B_WIDE : std_logic_vector(7 downto 0);
-- CPU
SIGNAL CPU_6502_RESET : STD_LOGIC;
......
RESET_N => RESET_N,
MEMORY_READY_CPU => MEMORY_READY_CPU,
MEMORY_READY_ANTIC => MEMORY_READY_ANTIC,
ANTIC_REFRESH => ANTIC_REFRESH_CYCLE,
PAUSE_6502 => HALT,
THROTTLE_COUNT_6502 => THROTTLE_COUNT_6502,
ANTIC_ENABLE_179 => ANTIC_ENABLE_179,
......
dma_fetch_out => ANTIC_FETCH,
hcount_out => hcount_temp,
vcount_out => vcount_temp,
refresh_out => ANTIC_REFRESH,
refresh_out => ANTIC_REFRESH_CYCLE,
AN => ANTIC_AN,
DATA_OUT => ANTIC_DO,
dma_address_out => ANTIC_ADDR);
......
pokey2 : entity work.pokey
PORT MAP(CLK => CLK,
CPU_MEMORY_READY => MEMORY_READY_CPU,
ANTIC_MEMORY_READY => MEMORY_READY_ANTIC,
ENABLE_179 => ENABLE_179_MEMWAIT,
WR_EN => POKEY2_WRITE_ENABLE,
RESET_N => RESET_N,
ADDR => PBI_ADDR_INT(3 DOWNTO 0),
......
CPU_FETCH => CPU_FETCH,
CPU_WRITE_N => R_W_N,
ANTIC_FETCH => ANTIC_FETCH,
antic_refresh => ANTIC_REFRESH,
DMA_FETCH => DMA_FETCH,
DMA_READ_ENABLE => DMA_READ_ENABLE,
DMA_32BIT_WRITE_ENABLE => DMA_32BIT_WRITE_ENABLE,
......
SDRAM_READ_EN => SDRAM_READ_ENABLE,
SDRAM_WRITE_EN => SDRAM_WRITE_ENABLE,
SDRAM_REQUEST => SDRAM_REQUEST,
SDRAM_REFRESH => SDRAM_REFRESH,
MEMORY_DATA => MEMORY_DATA,
PBI_ADDR => PBI_ADDR_INT,
RAM_ADDR => RAM_ADDR,
......
pokey1 : entity work.pokey
PORT MAP(CLK => CLK,
CPU_MEMORY_READY => MEMORY_READY_CPU,
ANTIC_MEMORY_READY => MEMORY_READY_ANTIC,
ENABLE_179 => ENABLE_179_MEMWAIT,
WR_EN => POKEY_WRITE_ENABLE,
RESET_N => RESET_N,
SIO_IN1 => SIO_RXD,
......
gtia1 : entity work.gtia
PORT MAP(CLK => CLK,
WR_EN => GTIA_WRITE_ENABLE,
CPU_MEMORY_READY => MEMORY_READY_CPU,
ANTIC_MEMORY_READY => MEMORY_READY_ANTIC,
ANTIC_FETCH => ANTIC_FETCH,
CPU_ENABLE_ORIGINAL => ENABLE_179_MEMWAIT,
ANTIC_FETCH => ANTIC_FETCH, -- for first pmg fetch
CPU_ENABLE_ORIGINAL => ENABLE_179_MEMWAIT, -- for subsequent pmg fetches
RESET_N => RESET_N,
PAL => PAL,
COLOUR_CLOCK_ORIGINAL => ANTIC_ORIGINAL_COLOUR_CLOCK_OUT,
......
AN => ANTIC_AN,
CPU_DATA_IN => WRITE_DATA(7 DOWNTO 0),
MEMORY_DATA_IN => MEMORY_DATA(7 DOWNTO 0),
VSYNC => VGA_VS,
HSYNC => VGA_HS,
BLANK => open,
VSYNC => VIDEO_VS,
HSYNC => VIDEO_HS,
BLANK => VIDEO_BLANK,
BURST => VIDEO_BURST,
START_OF_FIELD => VIDEO_START_OF_FIELD,
ODD_LINE => VIDEO_ODD_LINE,
sound => GTIA_SOUND,
COLOUR_out => COLOUR,
DATA_OUT => GTIA_DO);
......
--Ultramarine 7, 112 Orange 15, 240
gen_palette_none : if palette=0 generate
VGA_B <= COLOUR;
VGA_R <= (others => '0');
VGA_G <= (others => '0');
VIDEO_B_WIDE <= COLOUR;
VIDEO_R_WIDE <= (others => '0');
VIDEO_G_WIDE <= (others => '0');
end generate;
gen_palette_altirra : if palette=1 generate
palette1 : entity work.gtia_palette(altirra)
port map (ATARI_COLOUR=>COLOUR, R_next=>VGA_R_WIDE, G_next=>VGA_G_WIDE, B_next=>VGA_B_WIDE);
port map (ATARI_COLOUR=>COLOUR, R_next=>VIDEO_R_WIDE, G_next=>VIDEO_G_WIDE, B_next=>VIDEO_B_WIDE);
end generate;
gen_palette_laoo : if palette=2 generate
palette2 : entity work.gtia_palette(laoo)
port map (ATARI_COLOUR=>COLOUR, R_next=>VGA_R_WIDE, G_next=>VGA_G_WIDE, B_next=>VGA_B_WIDE);
port map (ATARI_COLOUR=>COLOUR, R_next=>VIDEO_R_WIDE, G_next=>VIDEO_G_WIDE, B_next=>VIDEO_B_WIDE);
end generate;
VGA_R(video_bits-1 downto 0) <= VGA_R_WIDE(7 downto 8-video_bits);
VGA_G(video_bits-1 downto 0) <= VGA_G_WIDE(7 downto 8-video_bits);
VGA_B(video_bits-1 downto 0) <= VGA_B_WIDE(7 downto 8-video_bits);
VIDEO_R(video_bits-1 downto 0) <= VIDEO_R_WIDE(7 downto 8-video_bits);
VIDEO_G(video_bits-1 downto 0) <= VIDEO_G_WIDE(7 downto 8-video_bits);
VIDEO_B(video_bits-1 downto 0) <= VIDEO_B_WIDE(7 downto 8-video_bits);
irq_glue1 : entity work.irq_glue
PORT MAP(pokey_irq => POKEY_IRQ,
......
-- outputs
PBI_ADDR <= PBI_ADDR_INT;
PORTB_OUT <= PORTB_OUT_INT;
ANTIC_REFRESH <= ANTIC_REFRESH_CYCLE;
END bdf_type;
common/a8core/atari800core_helloworld.vhd
video_bits : integer := 8;
internal_rom : integer :=1;
internal_ram : integer := 16384 -- at start of memory map
);
PORT
......
RESET_N : IN STD_LOGIC;
-- VIDEO OUT - PAL/NTSC, original Atari timings approx (may be higher res)
VGA_VS : OUT STD_LOGIC;
VGA_HS : OUT STD_LOGIC;
VGA_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_VS : OUT STD_LOGIC;
VIDEO_HS : OUT STD_LOGIC;
VIDEO_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
-- AUDIO OUT - Pokey/GTIA 1-bit and Covox all mixed
-- TODO - choose stereo/mono pokey
......
GENERIC MAP
(
cycle_length => cycle_length,
internal_rom => 1,
internal_rom => internal_rom,
internal_ram =>internal_ram,
video_bits => video_bits
)
......
CLK => CLK,
RESET_N => RESET_N,
VGA_VS => VGA_VS,
VGA_HS => VGA_HS,
VGA_B => VGA_B,
VGA_G => VGA_G,
VGA_R => VGA_R,
VIDEO_VS => VIDEO_VS,
VIDEO_HS => VIDEO_HS,
VIDEO_B => VIDEO_B,
VIDEO_G => VIDEO_G,
VIDEO_R => VIDEO_R,
VIDEO_BLANK => open,
VIDEO_BURST => open,
VIDEO_START_OF_FIELD => open,
VIDEO_ODD_LINE => open,
AUDIO_L => AUDIO_L,
AUDIO_R => AUDIO_R,
common/a8core/atari800core_simple_sdram.vhd
-- how many bits for video
video_bits : integer := 8;
palette : integer :=1; -- 0:gtia colour on VIDEO_B, 1:altirra, 2:laoo
-- For initial port may help to have no
internal_rom : integer := 1; -- if 0 expects it in sdram,is 1:16k os+basic, is 2:... TODO
......
RESET_N : IN STD_LOGIC;
-- VIDEO OUT - PAL/NTSC, original Atari timings approx (may be higher res)
VGA_VS : OUT STD_LOGIC;
VGA_HS : OUT STD_LOGIC;
VGA_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VGA_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_VS : OUT STD_LOGIC;
VIDEO_HS : OUT STD_LOGIC;
VIDEO_B : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_G : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
VIDEO_R : OUT STD_LOGIC_VECTOR(video_bits-1 DOWNTO 0);
-- These ones are probably only needed for e.g. svideo
VIDEO_BLANK : out std_logic;
VIDEO_BURST : out std_logic;
VIDEO_START_OF_FIELD : out std_logic;
VIDEO_ODD_LINE : out std_logic;
-- AUDIO OUT - Pokey/GTIA 1-bit and Covox all mixed
-- TODO - choose stereo/mono pokey
......
SDRAM_32BIT_WRITE_ENABLE : out std_logic;
SDRAM_16BIT_WRITE_ENABLE : out std_logic;
SDRAM_8BIT_WRITE_ENABLE : out std_logic;
SDRAM_REFRESH : out std_logic;
-- DMA memory map differs
-- e.g. some special addresses to read behind hardware registers
......
-- ANTIC
signal ANTIC_LIGHTPEN : std_logic;
signal ANTIC_REFRESH : std_logic;
signal ANTIC_REFRESH_END : std_logic;
signal SDRAM_REFRESH_NEXT : std_logic;
signal SDRAM_REFRESH_REG : std_logic;
-- CARTRIDGE ACCESS
SIGNAL CART_RD4 : STD_LOGIC;
......
-- ANTIC lightpen
ANTIC_LIGHTPEN <= JOY2_n(4) and JOY1_n(4);
-- ANTIC REFRESH - provide hint to SDRAM of a good time to refresh
process(clk,reset_n)
begin
if (reset_n='0') then
SDRAM_REFRESH_REG <= '0';
elsif (clk'event and clk='1') then
SDRAM_REFRESH_REG <= SDRAM_REFRESH_NEXT;
end if;
end process;
process(ANTIC_REFRESH, ANTIC_REFRESH_END, SDRAM_REFRESH_REG)
begin
SDRAM_REFRESH_NEXT <= SDRAM_REFRESH_REG;
if (ANTIC_REFRESH = '1') then
SDRAM_REFRESH_NEXT <= '1';
end if;
if (ANTIC_REFRESH_END = '1') then
SDRAM_REFRESH_NEXT <= '0';
end if;
end process;
refresh_delay : entity work.delay_line
generic map (COUNT=>cycle_length)
port map(clk=>clk,sync_reset=>'0',data_in=>ANTIC_REFRESH,enable=>'1',reset_n=>reset_n,data_out=>ANTIC_REFRESH_END);
SDRAM_REFRESH <= SDRAM_REFRESH_NEXT;
-- GTIA triggers
GTIA_TRIG <= CART_RD5&"1"&JOY2_n(4)&JOY1_n(4);
......
GENERIC MAP
(
cycle_length => cycle_length,
video_bits => video_bits
video_bits => video_bits,
palette => palette
)
PORT MAP
(
CLK => CLK,
RESET_N => RESET_N,
VGA_VS => VGA_VS,
VGA_HS => VGA_HS,
VGA_B => VGA_B,
VGA_G => VGA_G,
VGA_R => VGA_R,
VIDEO_VS => VIDEO_VS,
VIDEO_HS => VIDEO_HS,
VIDEO_B => VIDEO_B,
VIDEO_G => VIDEO_G,
VIDEO_R => VIDEO_R,
VIDEO_BLANK => VIDEO_BLANK,
VIDEO_BURST => VIDEO_BURST,
VIDEO_START_OF_FIELD => VIDEO_START_OF_FIELD,
VIDEO_ODD_LINE => VIDEO_ODD_LINE,
AUDIO_L => AUDIO_L,
AUDIO_R => AUDIO_R,
......
GTIA_TRIG => GTIA_TRIG,
ANTIC_LIGHTPEN => ANTIC_LIGHTPEN,
ANTIC_REFRESH => ANTIC_REFRESH,
SDRAM_REQUEST => SDRAM_REQUEST,
SDRAM_REQUEST_COMPLETE => SDRAM_REQUEST_COMPLETE,
......
SDRAM_ADDR => SDRAM_ADDR,
SDRAM_DO => SDRAM_DO,
SDRAM_REFRESH => open, -- TODO
RAM_ADDR => RAM_ADDR,
RAM_DO => RAM_DO,
RAM_REQUEST => RAM_REQUEST,
common/a8core/enable_divider.vhdl
process(clk,reset_n)
begin
if (reset_n = '0') then
count_reg <= (others=>'0');
count_reg <=std_logic_vector(to_unsigned(COUNT-1,WIDTH));
enabled_out_reg <= '0';
elsif (clk'event and clk='1') then
count_reg <= count_next;
common/a8core/gtia.vhdl
WR_EN : IN STD_LOGIC;
MEMORY_DATA_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CPU_MEMORY_READY : IN STD_LOGIC;
ANTIC_MEMORY_READY : IN STD_LOGIC;
ANTIC_FETCH : IN STD_LOGIC;
ANTIC_FETCH : in std_logic;
CPU_ENABLE_ORIGINAL : in std_logic;
CPU_ENABLE_ORIGINAL : in std_logic; -- on cycle data is ready
RESET_N : IN STD_LOGIC;
......
VSYNC : out std_logic;
HSYNC : out std_logic;
BLANK : out std_logic;
BURST : out std_logic;
START_OF_FIELD : out std_logic;
ODD_LINE : out std_logic;
-- To speaker
sound : out std_logic
......
signal hsync_start : std_logic;
signal hsync_end : std_logic;
signal burst_next : std_logic;
signal burst_reg : std_logic;
signal burst_start : std_logic;
signal burst_end : std_logic;
signal hblank_next : std_logic;
signal hblank_reg : std_logic;
......
constant pmg_dma_done : std_logic_vector(2 downto 0) := "101";
constant pmg_dma_instruction : std_logic_vector(2 downto 0) := "110";
signal memory_ready : std_logic;
begin
-- register
process(clk,reset_n)
......
vsync_reg <= '0';
hsync_reg <= '0';
burst_reg <= '0';
hblank_reg <= '0';
an_prev_reg <= (others=>'0');
......
vsync_reg <= vsync_next;
hsync_reg <= hsync_next;
burst_reg <= burst_next;
hblank_reg <= hblank_next;
an_prev_reg <= an_prev_next;
......
vsync_next <= vsync_reg;
odd_scanline_next <= odd_scanline_reg;
start_of_field <= '0';
-- NB high res mode gives pf2 - which is or of the two pixels
highres_next <= highres_reg;
......
odd_scanline_next <= '0';
visible_live <= '0';
start_of_field <= not(vsync_reg);
end if;
-- during vblank we reset our own counter - since Antic does not clear hblank_reg
......
-- end process;
-- generate hsync
process(hpos_reg, hsync_reg, hsync_end, vsync_reg, vsync_next)
process(hpos_reg, hsync_reg, hsync_end, burst_reg, burst_end, vsync_reg, vsync_next)
begin
hsync_start <= '0';
hsync_next <= hsync_reg;
burst_start <= '0';
burst_next <= burst_reg;
if (unsigned(hpos_reg) = X"D4" and vsync_reg = '1') then
hsync_start <= '1';
......
hsync_start <= '1';
hsync_next <= '1';
end if;
if (unsigned(hpos_reg) = X"14" and vsync_reg = '0' ) then
burst_start <= '1';
burst_next <= '1';
end if;
if (hsync_end = '1') then
hsync_next <= '0';
end if;
if (burst_end = '1') then
burst_next <= '0';
end if;
if (vsync_next = '0' and vsync_reg = '1') then
hsync_next <= '0';
......
generic map (COUNT=>15)
port map(clk=>clk,sync_reset=>'0',data_in=>hsync_start,enable=>COLOUR_CLOCK_ORIGINAL,reset_n=>reset_n,data_out=>hsync_end);
burst_delay : delay_line
generic map (COUNT=>8)
port map(clk=>clk,sync_reset=>'0',data_in=>burst_start,enable=>COLOUR_CLOCK_ORIGINAL,reset_n=>reset_n,data_out=>burst_end);
-- pmg dma
MEMORY_READY <= CPU_MEMORY_READY or ANTIC_MEMORY_READY; -- TODO, REVIEW timing vs CPU/ANTIC - simpler may be possible now
process(antic_fetch,CPU_ENABLE_ORIGINAL,memory_ready,memory_data_in,hsync_start,pmg_dma_state_reg,gractl_reg,odd_scanline_reg,vdelay_reg,grafm_reg, visible_live,hpos_reg, hblank_reg)
process(CPU_ENABLE_ORIGINAL,antic_fetch,memory_data_in,hsync_start,pmg_dma_state_reg,gractl_reg,odd_scanline_reg,vdelay_reg,grafm_reg, visible_live,hpos_reg, hblank_reg)
begin
pmg_dma_state_next <= pmg_dma_state_reg;
grafm_dma_load <= '0';
......
pmg_dma_state_next <= pmg_dma_missile;
end if;
-- we start from the first antic refresh cycle
-- we start from the first antic fetch
-- TODO - CPU enable does not identify next 'antic' cycle in turbo mode...
case pmg_dma_state_reg is
when pmg_dma_missile =>
if (antic_fetch = '1' and memory_ready = '1' and hblank_reg = '1' and visible_live = '0' and hpos_reg(7 downto 4) = "0000") then
if (antic_fetch = '1' and cpu_enable_original = '1' and hblank_reg = '1' and visible_live = '0' and hpos_reg(7 downto 4) = "0000") then
-- here we have the missile0
grafm_dma_load <= gractl_reg(0);
......
pmg_dma_state_next <= pmg_dma_instruction;
end if;
when pmg_dma_instruction =>
if (((CPU_ENABLE_ORIGINAL or antic_fetch) and memory_ready) = '1') then
if (CPU_ENABLE_ORIGINAL = '1') then
pmg_dma_state_next <= pmg_dma_player0;
end if;
when pmg_dma_player0 =>
if (((CPU_ENABLE_ORIGINAL or antic_fetch) and memory_ready) = '1') then
if (CPU_ENABLE_ORIGINAL = '1') then
-- here we have player0
grafp0_dma_next <= memory_data_in;
grafp0_dma_load <= gractl_reg(1) and (odd_scanline_reg or not(vdelay_reg(4)));
pmg_dma_state_next <= pmg_dma_player1;
end if;
when pmg_dma_player1 =>
if (((CPU_ENABLE_ORIGINAL or antic_fetch) and memory_ready) = '1') then
if (CPU_ENABLE_ORIGINAL = '1') then
-- here we have player1
grafp1_dma_next <= memory_data_in;
grafp1_dma_load <= gractl_reg(1) and (odd_scanline_reg or not(vdelay_reg(5)));
pmg_dma_state_next <= pmg_dma_player2;
end if;
when pmg_dma_player2 =>
if (((CPU_ENABLE_ORIGINAL or antic_fetch) and memory_ready) = '1') then
if (CPU_ENABLE_ORIGINAL = '1') then
-- here we have player1
grafp2_dma_next <= memory_data_in;
grafp2_dma_load <= gractl_reg(1) and (odd_scanline_reg or not(vdelay_reg(6)));
pmg_dma_state_next <= pmg_dma_player3;
end if;
when pmg_dma_player3 =>
if (((CPU_ENABLE_ORIGINAL or antic_fetch) and memory_ready) = '1') then
if (CPU_ENABLE_ORIGINAL = '1') then
-- here we have player1
grafp3_dma_next <= memory_data_in;
grafp3_dma_load <= gractl_reg(1) and (odd_scanline_reg or not(vdelay_reg(7)));
......
vsync<=vsync_reg;
hsync<=hsync_reg;
blank<=hblank_reg or vsync_reg;
burst<=burst_reg;
odd_line<=odd_scanline_reg;
sound <= consol_output_reg(3);
common/a8core/pokey.vhdl
PORT
(
CLK : IN STD_LOGIC;
--ENABLE_179 :in std_logic;
CPU_MEMORY_READY :in std_logic;
ANTIC_MEMORY_READY :in std_logic;
ENABLE_179 :in std_logic;
ADDR : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
DATA_IN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
WR_EN : IN STD_LOGIC;
......
signal pot_reset_next : std_logic;
signal pot_reset_reg : std_logic;
signal enable_179 : std_logic;
BEGIN
--HACK FIXME TODO
enable_179 <= cpu_MEMORY_READY or antIC_MEMORY_READY;
-- register
process(clk,reset_n)
begin
common/a8core/shared_enable.vhdl
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE ieee.math_real.ceil;
USE ieee.math_real.log2;
-- TODO - review this whole scheme
-- Massively overcomplex and turbo doesn't even work with it right now!
......
(
CLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
ANTIC_REFRESH : IN STD_LOGIC;
MEMORY_READY_CPU : IN STD_LOGIC; -- during memory wait states keep CPU awake
MEMORY_READY_ANTIC : IN STD_LOGIC; -- during memory wait states keep CPU awake
PAUSE_6502 : in std_logic;
THROTTLE_COUNT_6502 : in std_logic_vector(5 downto 0);
ANTIC_ENABLE_179 : OUT STD_LOGIC; -- always about 1.79MHz to keep sound the same - 1 cycle early
oldcpu_enable : OUT STD_LOGIC; -- always about 1.79MHz to keep sound the same - expanded to next ready
oldcpu_enable : OUT STD_LOGIC; -- always about 1.79MHz to keep sound the same - 1 cycle only, when memory is ready...
CPU_ENABLE_OUT : OUT STD_LOGIC -- for compatibility run at 1.79MHz, for speed run as fast as we can
-- antic DMA runs 1 cycle after 'enable', so ANTIC_ENABLE is delayed by 31 cycles vs CPU_ENABLE (when in 1.79MHz mode)
-- XXX watch out on clock speed change from 56MHz!
-- antic DMA runs 1 cycle after 'enable', so ANTIC_ENABLE is delayed by cycle_length-1 cycles vs CPU_ENABLE (when in 1.79MHz mode)
);
END shared_enable;
......
signal cpu_extra_enable_next : std_logic;
signal cpu_extra_enable_reg : std_logic;
signal turbo_next : std_logic;
signal turbo_reg : std_logic;
signal throttle_count_next : std_logic_vector(5 downto 0);
signal throttle_count_reg : std_logic_vector(5 downto 0);
signal speed_shift_next : std_logic_vector(cycle_length-1 downto 0);
signal speed_shift_reg : std_logic_vector(cycle_length-1 downto 0);
-- TODO - clean up
signal oldcpu_extra_enable_next : std_logic;
signal oldcpu_extra_enable_reg : std_logic;
signal enable_179_expanded : std_logic;
signal oldcpu_pending_next : std_logic;
signal oldcpu_pending_reg : std_logic;
signal oldcpu_go : std_logic;
signal memory_ready : std_logic;
constant cycle_length_bits: integer := integer(ceil(log2(real(cycle_length))));
begin
-- instantiate some clock calcs
enable_179_clock_div : enable_divider
generic map (COUNT=>cycle_length)
port map(clk=>clk,reset_n=>reset_n,enable_in=>'1',enable_out=>enable_179);
process(THROTTLE_COUNT_6502, throttle_count_reg, enable_179)
process(THROTTLE_COUNT_6502, speed_shift_reg, enable_179)
variable speed_shift : std_logic;
variable speed_shift_temp : std_logic_vector(cycle_length-1 downto 0);
begin
turbo_next <= '0';
throttle_count_next <= std_logic_vector(unsigned(throttle_count_reg) + 1);
--011111/31/1f = run every 32 cycles
if (throttle_count_reg = THROTTLE_COUNT_6502) then
throttle_count_next <= (others=>'0');
turbo_next <= '1';
end if;
if (enable_179 = '1') then -- synchronize
throttle_count_next <= "000001";
speed_shift_temp(cycle_length-1 downto 1) := (others=>'0');
speed_shift_temp(0) := '1';
else
speed_shift_temp := speed_shift_reg;
end if;
--0000000000111111111122222222223333
--0123456789012345678901234567890123
--X-------------------------------X
--
--000000000011111111112222222222333
--R12345678901234567890123456789012
---------------------------------NT
speed_shift_next(cycle_length-1 downto 1) <= speed_shift_temp(cycle_length-2 downto 0);
--000000000011111100000000001111111
--R12345678901234501234567890123456
-----------------NT--------------NT
speed_shift := '0';
for i in 0 to cycle_length_bits loop
speed_shift := speed_shift or (speed_shift_temp(cycle_length/(2**i)-1) and throttle_count_6502(i));
end loop;
speed_shift_next(0) <= speed_shift;
end process;
delay_line_phase : delay_line
......
begin
if (reset_n = '0') then
cpu_extra_enable_reg <= '0';
oldcpu_extra_enable_reg <= '0';
turbo_reg <= '0';
throttle_count_reg <= (others=>'0');
oldcpu_pending_reg <= '0';
speed_shift_reg <= (others=>'0');
elsif (clk'event and clk='1') then
cpu_extra_enable_reg <= cpu_extra_enable_next;
oldcpu_extra_enable_reg <= oldcpu_extra_enable_next;
turbo_reg <= turbo_next;
throttle_count_reg <= throttle_count_next;
oldcpu_pending_reg <= oldcpu_pending_next;
speed_shift_reg <= speed_shift_next;
end if;
end process;
-- next state
memory_ready <= memORY_READY_CPU or memORY_READY_ANTIC;
cpu_enable <= (turbo_reg or cpu_extra_enable_reg or enable_179) and not(pause_6502);
cpu_enable <= (speed_shift_reg(0) or cpu_extra_enable_reg or enable_179) and not(pause_6502 or antic_refresh);
cpu_extra_enable_next <= cpu_enable and not(memory_ready);
oldcpu_extra_enable_next <= enable_179_expanded and not(memory_ready);
enable_179_expanded <= oldcpu_extra_enable_reg or enable_179;
oldcpu_pending_next <= (oldcpu_pending_reg or enable_179) and not(memory_ready or antic_refresh);
oldcpu_go <= (oldcpu_pending_reg or enable_179) and (memory_ready or antic_refresh);
-- output
oldcpu_enable <= enable_179_expanded;
oldcpu_enable <= oldcpu_go;
ANTIC_ENABLE_179 <= enable_179_early;
CPU_ENABLE_OUT <= cpu_enable; -- run at 25MHz

Also available in: Unified diff