mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-20 17:47:33 +00:00
Merge pull request #49 from gyurco/master
MCR1: use fixed CTC, common inputs
This commit is contained in:
commit
20cb265ceb
@ -217,8 +217,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/Kickman_MiST.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/kick.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/kick_sound_board.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ctc_counter.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ctc_controler.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/midssio_82s123.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/kick_sp_bits.vhd
|
||||
@ -227,6 +225,7 @@ set_global_assignment -name VHDL_FILE rtl/rom/kick_bg_bits_1.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
|
||||
set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@ -50,13 +50,16 @@ module Kickman_MiST(
|
||||
localparam CONF_STR = {
|
||||
"KICKMAN;;",
|
||||
"O2,Rotate Controls,Off,On;",
|
||||
"O34,Scanlines,Off,25%,50%,75%;",
|
||||
"O5,Blend,Off,On;",
|
||||
"O6,Service,Off,On;",
|
||||
"T0,Reset;",
|
||||
"V,v1.0.",`BUILD_DATE
|
||||
};
|
||||
|
||||
wire rotate = status[2];
|
||||
wire blend = status[5];
|
||||
wire service = status[6];
|
||||
|
||||
assign LED = ~ioctl_downl;
|
||||
assign SDRAM_CLK = clk_sys;
|
||||
assign SDRAM_CKE = 1;
|
||||
@ -81,6 +84,10 @@ wire [15:0] audio_l, audio_r;
|
||||
wire hs, vs, cs;
|
||||
wire blankn;
|
||||
wire [3:0] g, r, b;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
wire [14:0] rom_addr;
|
||||
wire [15:0] rom_do;
|
||||
wire [13:0] snd_addr;
|
||||
@ -162,7 +169,7 @@ wire [3:0] spin_angle;
|
||||
spinner spinner (
|
||||
.clock_40(clk_sys),
|
||||
.reset(reset),
|
||||
.btn_acc(m_fire),
|
||||
.btn_acc(m_fireA),
|
||||
.btn_left(m_left),
|
||||
.btn_right(m_right),
|
||||
.ctc_zc_to_2(ctc_zc_to2),
|
||||
@ -183,14 +190,14 @@ kick kick(
|
||||
.separate_audio(1'b0),
|
||||
.audio_out_l(audio_l),
|
||||
.audio_out_r(audio_r),
|
||||
.coin1(btn_coin),
|
||||
.coin2(1'b0),
|
||||
.start2(btn_two_players),
|
||||
.start1(btn_one_player),
|
||||
.coin1(m_coin1),
|
||||
.coin2(m_coin2),
|
||||
.start1(m_one_player),
|
||||
.start2(m_two_players),
|
||||
.kick(m_down),
|
||||
.ctc_zc_to_2(ctc_zc_to2),
|
||||
.spin_angle(spin_angle),
|
||||
.service(status[6]),
|
||||
.service(service),
|
||||
.cpu_rom_addr ( rom_addr ),
|
||||
.cpu_rom_do ( rom_addr[0] ? rom_do[15:8] : rom_do[7:0] ),
|
||||
.snd_rom_addr ( snd_addr ),
|
||||
@ -217,12 +224,12 @@ mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video(
|
||||
.VGA_B ( VGA_B ),
|
||||
.VGA_VS ( vs_out ),
|
||||
.VGA_HS ( hs_out ),
|
||||
.rotate ( {1'b1,status[2]} ),
|
||||
.rotate ( { 1'b1, rotate } ),
|
||||
.ce_divider ( 1'b1 ),
|
||||
.blend ( status[5] ),
|
||||
.blend ( blend ),
|
||||
.scandoubler_disable( 1'b1 ),
|
||||
.no_csync ( 1'b1 ),
|
||||
.scanlines ( status[4:3] ),
|
||||
.scanlines ( ),
|
||||
.ypbpr ( ypbpr )
|
||||
);
|
||||
|
||||
@ -265,43 +272,24 @@ dac_r(
|
||||
.dac_o(AUDIO_R)
|
||||
);
|
||||
|
||||
// Rotated Normal
|
||||
//wire m_up = ~status[2] ? btn_left | joystick_0[1] | joystick_1[1] : btn_up | joystick_0[3] | joystick_1[3];
|
||||
wire m_down = ~status[2] ? btn_right | joystick_0[0] | joystick_1[0] : btn_down | joystick_0[2] | joystick_1[2];
|
||||
wire m_left = ~status[2] ? btn_down | joystick_0[2] | joystick_1[2] : btn_left | joystick_0[1] | joystick_1[1];
|
||||
wire m_right = ~status[2] ? btn_up | joystick_0[3] | joystick_1[3] : btn_right | joystick_0[0] | joystick_1[0];
|
||||
wire m_fire = btn_fire1 | joystick_0[4] | joystick_1[4];
|
||||
//wire m_bomb = btn_fire2 | joystick_0[5] | joystick_1[5];
|
||||
wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF;
|
||||
wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F;
|
||||
wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
|
||||
|
||||
reg btn_one_player = 0;
|
||||
reg btn_two_players = 0;
|
||||
reg btn_left = 0;
|
||||
reg btn_right = 0;
|
||||
reg btn_down = 0;
|
||||
reg btn_up = 0;
|
||||
reg btn_fire1 = 0;
|
||||
//reg btn_fire2 = 0;
|
||||
//reg btn_fire3 = 0;
|
||||
reg btn_coin = 0;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if(key_strobe) begin
|
||||
case(key_code)
|
||||
'h75: btn_up <= key_pressed; // up
|
||||
'h72: btn_down <= key_pressed; // down
|
||||
'h6B: btn_left <= key_pressed; // left
|
||||
'h74: btn_right <= key_pressed; // right
|
||||
'h76: btn_coin <= key_pressed; // ESC
|
||||
'h05: btn_one_player <= key_pressed; // F1
|
||||
'h06: btn_two_players <= key_pressed; // F2
|
||||
// 'h14: btn_fire3 <= key_pressed; // ctrl
|
||||
// 'h11: btn_fire2 <= key_pressed; // alt
|
||||
'h29: btn_fire1 <= key_pressed; // Space
|
||||
endcase
|
||||
end
|
||||
end
|
||||
arcade_inputs inputs (
|
||||
.clk ( clk_sys ),
|
||||
.key_strobe ( key_strobe ),
|
||||
.key_pressed ( key_pressed ),
|
||||
.key_code ( key_code ),
|
||||
.joystick_0 ( joystick_0 ),
|
||||
.joystick_1 ( joystick_1 ),
|
||||
.rotate ( rotate ),
|
||||
.orientation ( 2'b11 ),
|
||||
.joyswap ( 1'b0 ),
|
||||
.oneplayer ( 1'b1 ),
|
||||
.controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
|
||||
.player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
|
||||
.player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@ -216,30 +216,14 @@ architecture struct of kick is
|
||||
signal cpu_ioreq_n : std_logic;
|
||||
signal cpu_irq_n : std_logic;
|
||||
signal cpu_m1_n : std_logic;
|
||||
|
||||
signal ctc_controler_we : std_logic;
|
||||
signal ctc_controler_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_int_ack : std_logic;
|
||||
signal cpu_int_ack_n : std_logic;
|
||||
|
||||
signal ctc_counter_0_we : std_logic;
|
||||
-- signal ctc_counter_0_trg : std_logic;
|
||||
signal ctc_counter_0_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_0_int : std_logic;
|
||||
signal ctc_ce : std_logic;
|
||||
signal ctc_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal ctc_counter_1_we : std_logic;
|
||||
-- signal ctc_counter_1_trg : std_logic;
|
||||
signal ctc_counter_1_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_1_int : std_logic;
|
||||
|
||||
signal ctc_counter_2_we : std_logic;
|
||||
-- signal ctc_counter_2_trg : std_logic;
|
||||
signal ctc_counter_2_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_2_int : std_logic;
|
||||
|
||||
signal ctc_counter_3_we : std_logic;
|
||||
signal ctc_counter_3_trg : std_logic;
|
||||
signal ctc_counter_3_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_3_int : std_logic;
|
||||
signal ctc_counter_1_trg : std_logic;
|
||||
signal ctc_counter_2_trg : std_logic;
|
||||
signal ctc_counter_3_trg : std_logic;
|
||||
|
||||
-- signal cpu_rom_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
@ -409,6 +393,10 @@ begin
|
||||
else
|
||||
vs_cnt <= vs_cnt +1;
|
||||
end if;
|
||||
|
||||
if vcnt = 240 then video_vs <= '0'; end if;
|
||||
if vcnt = 242 then video_vs <= '1'; end if;
|
||||
|
||||
else
|
||||
hs_cnt <= hs_cnt + 1;
|
||||
end if;
|
||||
@ -418,8 +406,8 @@ begin
|
||||
vcnt >= 1 and vcnt < 241 then video_blankn <= '1';end if;
|
||||
|
||||
|
||||
if hs_cnt = 0 then hsync0 <= '0';
|
||||
elsif hs_cnt = 47 then hsync0 <= '1';
|
||||
if hs_cnt = 0 then hsync0 <= '0'; video_hs <= '0';
|
||||
elsif hs_cnt = 47 then hsync0 <= '1'; video_hs <= '1';
|
||||
end if;
|
||||
|
||||
if hs_cnt = 0 then hsync1 <= '0';
|
||||
@ -566,24 +554,16 @@ cpu_di <= cpu_rom_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12) < X"7"
|
||||
wram_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12) = X"7" else -- 7000-7FFF
|
||||
sp_ram_cache_do when cpu_mreq_n = '0' and cpu_addr(15 downto 9) = "1111000" else -- sprite ram 0xF000-0xF1FF
|
||||
bg_ram_do when cpu_mreq_n = '0' and cpu_addr(15 downto 10) = "111111" else -- video ram 0xFC00-0xFFFF
|
||||
ctc_controler_do when cpu_ioreq_n = '0' and cpu_m1_n = '0' else -- ctc ctrl (interrupt vector)
|
||||
ctc_do when cpu_int_ack_n = '0' or ctc_ce = '1' else -- ctc (interrupt vector or counter data)
|
||||
ssio_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 4) = X"0" else
|
||||
ctc_counter_3_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F3" else
|
||||
ctc_counter_2_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F2" else
|
||||
ctc_counter_1_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F1" else
|
||||
ctc_counter_0_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else
|
||||
X"FF";
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Misc registers : ctc write enable / interrupt acknowledge
|
||||
------------------------------------------------------------------------
|
||||
ctc_counter_3_trg <= '1' when (vcnt = 246 and tv15Khz_mode = '1') or (vcnt = 493 and tv15Khz_mode = '0')else '0';
|
||||
ctc_counter_3_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F3" else '0';
|
||||
ctc_counter_2_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F2" else '0';
|
||||
ctc_counter_1_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F1" else '0';
|
||||
ctc_counter_0_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else '0';
|
||||
ctc_controler_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else '0'; -- F0
|
||||
ctc_int_ack <= '1' when cpu_ioreq_n = '0' and cpu_m1_n = '0' else '0';
|
||||
cpu_int_ack_n <= cpu_ioreq_n or cpu_m1_n;
|
||||
ctc_ce <= '1' when cpu_ioreq_n = '0' and cpu_addr(7 downto 4) = x"F" else '0';
|
||||
ctc_counter_3_trg <= '1' when top_frame = '1' and ((vcnt = 246 and tv15Khz_mode = '1') or (vcnt = 493 and tv15Khz_mode = '0')) else '0';
|
||||
|
||||
------------------------------------------
|
||||
-- write enable / ram access from CPU --
|
||||
@ -780,92 +760,28 @@ port map(
|
||||
DO => cpu_do
|
||||
);
|
||||
|
||||
-- CTC interrupt controler Z80-CTC (MK3882)
|
||||
ctc_controler : entity work.ctc_controler
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_controler_we,
|
||||
int_ack => ctc_int_ack,
|
||||
|
||||
int_pulse_0 => ctc_counter_0_int,
|
||||
int_pulse_1 => ctc_counter_1_int,
|
||||
int_pulse_2 => ctc_counter_2_int,
|
||||
int_pulse_3 => ctc_counter_3_int,
|
||||
|
||||
d_out => ctc_controler_do,
|
||||
int_n => cpu_irq_n
|
||||
);
|
||||
|
||||
ctc_counter_0 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_0_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_0_do,
|
||||
zc_to => open, -- zc/to #0 (pin 7) connected to clk_trg #1 (pin 22) on schematics (seems to be not used)
|
||||
int_pulse => ctc_counter_0_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_1 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_1_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_1_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_1_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_2 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_2_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_2_do,
|
||||
zc_to => ctc_zc_to_2, -- used for spin angle decoder simulation
|
||||
int_pulse => ctc_counter_2_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_3 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_3_we,
|
||||
|
||||
clk_trg => ctc_counter_3_trg,
|
||||
|
||||
d_out => ctc_counter_3_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_3_int
|
||||
|
||||
-- Z80-CTC (MK3882)
|
||||
z80ctc : entity work.z80ctc_top
|
||||
port map (
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
din => cpu_do,
|
||||
cpu_din => cpu_di,
|
||||
dout => ctc_do,
|
||||
ce_n => not ctc_ce,
|
||||
cs => cpu_addr(1 downto 0),
|
||||
m1_n => cpu_m1_n,
|
||||
iorq_n => cpu_ioreq_n,
|
||||
rd_n => cpu_rd_n,
|
||||
int_n => cpu_irq_n,
|
||||
trg0 => '0',
|
||||
to0 => ctc_counter_1_trg,
|
||||
trg1 => ctc_counter_1_trg,
|
||||
to1 => open,
|
||||
trg2 => '0',
|
||||
to2 => ctc_zc_to_2,
|
||||
trg3 => ctc_counter_3_trg
|
||||
);
|
||||
|
||||
-- cpu program ROM 0x0000-0x6FFF
|
||||
|
||||
@ -217,14 +217,11 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/SolarFox_MiST.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/solarfox.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/solarfox_sound_board.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ctc_counter.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ctc_controler.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/midssio_82s123.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sp_bits_4.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sp_bits_3.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sp_bits_2.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sp_bits_1.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sound_cpu.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_bg_bits_2.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_bg_bits_1.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/sol_sp_bits.vhd
|
||||
@ -232,6 +229,7 @@ set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
|
||||
set_global_assignment -name QIP_FILE ../../../common/IO/Z80CTC/z80ctc.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip
|
||||
set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@ -51,13 +51,16 @@ module SolarFox_MiST(
|
||||
localparam CONF_STR = {
|
||||
"SOLARFOX;;",
|
||||
"O2,Rotate Controls,Off,On;",
|
||||
"O34,Scanlines,Off,25%,50%,75%;",
|
||||
"O5,Blend,Off,On;",
|
||||
"O6,Service,Off,On;",
|
||||
"T0,Reset;",
|
||||
"V,v1.1.",`BUILD_DATE
|
||||
};
|
||||
|
||||
wire rotate = status[2];
|
||||
wire blend = status[5];
|
||||
wire service = status[6];
|
||||
|
||||
assign LED = ~ioctl_downl;
|
||||
assign SDRAM_CLK = clk_sys;
|
||||
assign SDRAM_CKE= 1;
|
||||
@ -82,6 +85,10 @@ wire [15:0] audio_l, audio_r;
|
||||
wire hs, vs, cs;
|
||||
wire blankn;
|
||||
wire [3:0] g, r, b;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
wire [14:0] rom_addr;
|
||||
wire [15:0] rom_do;
|
||||
wire [13:0] snd_addr;
|
||||
@ -171,21 +178,21 @@ solarfox solarfox(
|
||||
.separate_audio(1'b0),
|
||||
.audio_out_l(audio_l),
|
||||
.audio_out_r(audio_r),
|
||||
.coin1(btn_coin),
|
||||
.coin2(1'b0),
|
||||
.fast1(btn_one_player),
|
||||
.fast2(btn_two_players),
|
||||
.service(status[6]),
|
||||
.fire1(m_fire),
|
||||
.fire2(m_fire),
|
||||
.coin1(m_coin1),
|
||||
.coin2(m_coin2),
|
||||
.fast1(m_one_player),
|
||||
.fast2(m_two_players),
|
||||
.service(service),
|
||||
.fire1(m_fireA),
|
||||
.fire2(m_fire2A),
|
||||
.left1(m_left),
|
||||
.right1(m_right),
|
||||
.up1(m_up),
|
||||
.down1(m_down),
|
||||
.left2(m_left),
|
||||
.right2(m_right),
|
||||
.up2(m_up),
|
||||
.down2(m_down),
|
||||
.left2(m_left2),
|
||||
.right2(m_right2),
|
||||
.up2(m_up2),
|
||||
.down2(m_down2),
|
||||
.cpu_rom_addr ( rom_addr ),
|
||||
.cpu_rom_do ( rom_addr[0] ? rom_do[15:8] : rom_do[7:0] ),
|
||||
.snd_rom_addr ( snd_addr ),
|
||||
@ -212,12 +219,12 @@ mist_video #(.COLOR_DEPTH(4), .SD_HCNT_WIDTH(10)) mist_video(
|
||||
.VGA_B ( VGA_B ),
|
||||
.VGA_VS ( vs_out ),
|
||||
.VGA_HS ( hs_out ),
|
||||
.rotate ( {1'b1,status[2]} ),
|
||||
.rotate ( { 1'b1, rotate } ),
|
||||
.ce_divider ( 1 ),
|
||||
.blend ( status[5] ),
|
||||
.blend ( blend ),
|
||||
.scandoubler_disable( 1'b1 ),
|
||||
.no_csync ( 1'b1 ),
|
||||
.scanlines ( status[4:3] ),
|
||||
.scanlines ( ),
|
||||
.ypbpr ( ypbpr )
|
||||
);
|
||||
|
||||
@ -260,43 +267,24 @@ dac_r(
|
||||
.dac_o(AUDIO_R)
|
||||
);
|
||||
|
||||
// Rotated Normal
|
||||
wire m_up = ~status[2] ? btn_left | joystick_0[1] | joystick_1[1] : btn_up | joystick_0[3] | joystick_1[3];
|
||||
wire m_down = ~status[2] ? btn_right | joystick_0[0] | joystick_1[0] : btn_down | joystick_0[2] | joystick_1[2];
|
||||
wire m_left = ~status[2] ? btn_down | joystick_0[2] | joystick_1[2] : btn_left | joystick_0[1] | joystick_1[1];
|
||||
wire m_right = ~status[2] ? btn_up | joystick_0[3] | joystick_1[3] : btn_right | joystick_0[0] | joystick_1[0];
|
||||
wire m_fire = btn_fire1 | joystick_0[4] | joystick_1[4];
|
||||
//wire m_bomb = btn_fire2 | joystick_0[5] | joystick_1[5];
|
||||
wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD, m_fireE, m_fireF;
|
||||
wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D, m_fire2E, m_fire2F;
|
||||
wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
|
||||
|
||||
reg btn_one_player = 0;
|
||||
reg btn_two_players = 0;
|
||||
reg btn_left = 0;
|
||||
reg btn_right = 0;
|
||||
reg btn_down = 0;
|
||||
reg btn_up = 0;
|
||||
reg btn_fire1 = 0;
|
||||
//reg btn_fire2 = 0;
|
||||
//reg btn_fire3 = 0;
|
||||
reg btn_coin = 0;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if(key_strobe) begin
|
||||
case(key_code)
|
||||
'h75: btn_up <= key_pressed; // up
|
||||
'h72: btn_down <= key_pressed; // down
|
||||
'h6B: btn_left <= key_pressed; // left
|
||||
'h74: btn_right <= key_pressed; // right
|
||||
'h76: btn_coin <= key_pressed; // ESC
|
||||
'h05: btn_one_player <= key_pressed; // F1
|
||||
'h06: btn_two_players <= key_pressed; // F2
|
||||
// 'h14: btn_fire3 <= key_pressed; // ctrl
|
||||
// 'h11: btn_fire2 <= key_pressed; // alt
|
||||
'h29: btn_fire1 <= key_pressed; // Space
|
||||
endcase
|
||||
end
|
||||
end
|
||||
arcade_inputs inputs (
|
||||
.clk ( clk_sys ),
|
||||
.key_strobe ( key_strobe ),
|
||||
.key_pressed ( key_pressed ),
|
||||
.key_code ( key_code ),
|
||||
.joystick_0 ( joystick_0 ),
|
||||
.joystick_1 ( joystick_1 ),
|
||||
.rotate ( rotate ),
|
||||
.orientation ( 2'b11 ),
|
||||
.joyswap ( 1'b0 ),
|
||||
.oneplayer ( 1'b1 ),
|
||||
.controls ( {m_tilt, m_coin4, m_coin3, m_coin2, m_coin1, m_four_players, m_three_players, m_two_players, m_one_player} ),
|
||||
.player1 ( {m_fireF, m_fireE, m_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
|
||||
.player2 ( {m_fire2F, m_fire2E, m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
---------------------------------------------------------------------------------
|
||||
-- Z80-CTC controler by Dar (darfpga@aol.fr) (19/10/2019)
|
||||
-- http://darfpga.blogspot.fr
|
||||
---------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ctc_controler is
|
||||
port(
|
||||
clock : in std_logic;
|
||||
clock_ena : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
d_in : in std_logic_vector( 7 downto 0);
|
||||
load_data : in std_logic;
|
||||
int_ack : in std_logic;
|
||||
|
||||
int_pulse_0 : in std_logic;
|
||||
int_pulse_1 : in std_logic;
|
||||
int_pulse_2 : in std_logic;
|
||||
int_pulse_3 : in std_logic;
|
||||
|
||||
d_out : out std_logic_vector( 7 downto 0);
|
||||
int_n : out std_logic
|
||||
|
||||
);
|
||||
end ctc_controler;
|
||||
|
||||
architecture struct of ctc_controler is
|
||||
|
||||
signal int_vector : std_logic_vector(4 downto 0);
|
||||
|
||||
signal wait_for_time_constant : std_logic;
|
||||
signal load_data_r : std_logic; -- make sure load_data toggles to get one new data
|
||||
|
||||
signal int_reg_0 : std_logic;
|
||||
signal int_reg_1 : std_logic;
|
||||
signal int_reg_2 : std_logic;
|
||||
signal int_reg_3 : std_logic;
|
||||
|
||||
signal int_ack_r : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
int_n <= '0' when (int_reg_0 or int_reg_1 or int_reg_2 or int_reg_3) = '1' else '1';
|
||||
|
||||
d_out <= int_vector & "000" when int_reg_0 = '1' else
|
||||
int_vector & "010" when int_reg_1 = '1' else
|
||||
int_vector & "100" when int_reg_2 = '1' else
|
||||
int_vector & "110" when int_reg_3 = '1' else (others => '0');
|
||||
|
||||
process (reset, clock)
|
||||
begin
|
||||
|
||||
if reset = '1' then -- hardware and software reset
|
||||
wait_for_time_constant <= '0';
|
||||
int_reg_0 <= '0';
|
||||
int_reg_1 <= '0';
|
||||
int_reg_2 <= '0';
|
||||
int_reg_3 <= '0';
|
||||
load_data_r <= load_data;
|
||||
int_vector <= (others => '0');
|
||||
else
|
||||
if rising_edge(clock) then
|
||||
if clock_ena = '1' then
|
||||
|
||||
load_data_r <= load_data;
|
||||
int_ack_r <= int_ack;
|
||||
|
||||
if load_data = '1' and load_data_r = '0' then
|
||||
|
||||
if wait_for_time_constant = '1' then
|
||||
wait_for_time_constant <= '0';
|
||||
else
|
||||
if d_in(0) = '1' then -- check if its a control world
|
||||
wait_for_time_constant <= d_in(2);
|
||||
-- if d_in(1) = '1' then -- software reset
|
||||
-- wait_for_time_constant <= '0';
|
||||
-- end if;
|
||||
else -- its an interrupt vector
|
||||
int_vector <= d_in(7 downto 3);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
if int_pulse_0 = '1' then int_reg_0 <= '1'; end if;
|
||||
if int_pulse_1 = '1' then int_reg_1 <= '1'; end if;
|
||||
if int_pulse_2 = '1' then int_reg_2 <= '1'; end if;
|
||||
if int_pulse_3 = '1' then int_reg_3 <= '1'; end if;
|
||||
|
||||
if int_ack_r = '1' and int_ack = '0' then
|
||||
if int_reg_0 = '1' then int_reg_0 <= '0';
|
||||
elsif int_reg_1 = '1' then int_reg_1 <= '0';
|
||||
elsif int_reg_2 = '1' then int_reg_2 <= '0';
|
||||
elsif int_reg_3 = '1' then int_reg_3 <= '0'; end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end struct;
|
||||
@ -1,152 +0,0 @@
|
||||
---------------------------------------------------------------------------------
|
||||
-- Z80-CTC counter by Dar (darfpga@aol.fr) (19/10/2019)
|
||||
-- http://darfpga.blogspot.fr
|
||||
---------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ctc_counter is
|
||||
port(
|
||||
clock : in std_logic;
|
||||
clock_ena : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
d_in : in std_logic_vector( 7 downto 0);
|
||||
load_data : in std_logic;
|
||||
|
||||
clk_trg : in std_logic;
|
||||
|
||||
d_out : out std_logic_vector(7 downto 0);
|
||||
zc_to : out std_logic;
|
||||
int_pulse : out std_logic
|
||||
|
||||
);
|
||||
end ctc_counter;
|
||||
|
||||
architecture struct of ctc_counter is
|
||||
|
||||
signal control_word : std_logic_vector(7 downto 0);
|
||||
signal wait_for_time_constant : std_logic;
|
||||
signal time_constant_loaded : std_logic;
|
||||
signal restart_on_next_clock : std_logic;
|
||||
signal restart_on_next_trigger : std_logic;
|
||||
|
||||
signal prescale_max : std_logic_vector(7 downto 0);
|
||||
signal prescale_in : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal count_max : std_logic_vector(8 downto 0);
|
||||
signal count_in : std_logic_vector(8 downto 0) := (others => '0');
|
||||
signal zc_to_in : std_logic;
|
||||
signal clk_trg_r : std_logic;
|
||||
signal trigger : std_logic;
|
||||
signal count_ena : std_logic;
|
||||
signal load_data_r : std_logic; -- make sure load_data toggles to get one new data
|
||||
|
||||
begin
|
||||
|
||||
prescale_max <=
|
||||
(others => '0') when control_word(6) = '1' else -- counter mode (prescale max = 0)
|
||||
X"0F" when control_word(6 downto 5) = "00" else -- timer mode prescale 16
|
||||
X"FF"; -- timer mode prescale 256
|
||||
|
||||
trigger <=
|
||||
'1' when (clk_trg = '0' and clk_trg_r = '1' and control_word(4) = '0') or -- falling edge
|
||||
(clk_trg = '1' and clk_trg_r = '0' and control_word(4) = '1') else '0'; -- rising edge
|
||||
|
||||
d_out <= count_in(7 downto 0);
|
||||
|
||||
zc_to <= zc_to_in;
|
||||
int_pulse <= zc_to_in when control_word(7) = '1' else '0';
|
||||
|
||||
process (reset, clock)
|
||||
begin
|
||||
|
||||
if reset = '1' then -- hardware reset
|
||||
count_ena <= '0';
|
||||
wait_for_time_constant <= '0';
|
||||
time_constant_loaded <= '0';
|
||||
restart_on_next_clock <= '0';
|
||||
restart_on_next_trigger <= '0';
|
||||
count_in <= (others=> '0');
|
||||
zc_to_in <= '0';
|
||||
clk_trg_r <= clk_trg;
|
||||
else
|
||||
if rising_edge(clock) then
|
||||
if clock_ena = '1' then
|
||||
|
||||
clk_trg_r <= clk_trg;
|
||||
load_data_r <= load_data;
|
||||
|
||||
if (restart_on_next_trigger = '1' and trigger = '1') or (restart_on_next_clock = '1') then
|
||||
restart_on_next_clock <= '0';
|
||||
restart_on_next_trigger <= '0';
|
||||
count_ena <= '1';
|
||||
count_in <= count_max;
|
||||
prescale_in <= prescale_max;
|
||||
end if;
|
||||
|
||||
if load_data = '1' and load_data_r = '0' then
|
||||
|
||||
if wait_for_time_constant = '1' then
|
||||
wait_for_time_constant <= '0';
|
||||
time_constant_loaded <= '1';
|
||||
|
||||
if d_in = X"00" then
|
||||
count_max <= '1'&X"00";
|
||||
else
|
||||
count_max <= '0'&d_in;
|
||||
end if;
|
||||
|
||||
if control_word(6) = '0' and count_ena = '0' then -- in timer mode, if count was stooped
|
||||
if control_word(3) = '0' then -- auto start when time_constant loaded
|
||||
restart_on_next_clock <= '1';
|
||||
else -- wait for trigger to start
|
||||
restart_on_next_trigger <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
else -- not waiting for time constant
|
||||
|
||||
if d_in(0) = '1' then -- check if its a control world
|
||||
control_word <= d_in;
|
||||
wait_for_time_constant <= d_in(2);
|
||||
restart_on_next_clock <= '0';
|
||||
restart_on_next_trigger <= '0';
|
||||
|
||||
if d_in(1) = '1' then -- software reset
|
||||
count_ena <= '0';
|
||||
time_constant_loaded <= '0';
|
||||
zc_to_in <= '0';
|
||||
-- zc_to_in_r <= '0';
|
||||
clk_trg_r <= clk_trg;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end if; -- end load data
|
||||
|
||||
-- counter
|
||||
zc_to_in <= '0';
|
||||
if ((control_word(6) = '1' and trigger = '1' ) or
|
||||
(control_word(6) = '0' and count_ena = '1') ) and time_constant_loaded = '1' then
|
||||
if prescale_in = 0 then
|
||||
prescale_in <= '0'&prescale_max(7 downto 1); -- test divide by 2 !
|
||||
if count_in = 0 then
|
||||
zc_to_in <= '1';
|
||||
count_in <= count_max;
|
||||
else
|
||||
count_in <= count_in - '1';
|
||||
end if;
|
||||
else
|
||||
prescale_in <= prescale_in - '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end struct;
|
||||
@ -219,33 +219,17 @@ architecture struct of solarfox is
|
||||
signal cpu_ioreq_n : std_logic;
|
||||
signal cpu_irq_n : std_logic;
|
||||
signal cpu_m1_n : std_logic;
|
||||
|
||||
signal ctc_controler_we : std_logic;
|
||||
signal ctc_controler_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_int_ack : std_logic;
|
||||
signal cpu_int_ack_n : std_logic;
|
||||
|
||||
signal ctc_counter_0_we : std_logic;
|
||||
-- signal ctc_counter_0_trg : std_logic;
|
||||
signal ctc_counter_0_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_0_int : std_logic;
|
||||
signal ctc_ce : std_logic;
|
||||
signal ctc_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal ctc_counter_1_trg : std_logic;
|
||||
signal ctc_counter_2_trg : std_logic;
|
||||
signal ctc_counter_3_trg : std_logic;
|
||||
|
||||
signal ctc_counter_1_we : std_logic;
|
||||
-- signal ctc_counter_1_trg : std_logic;
|
||||
signal ctc_counter_1_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_1_int : std_logic;
|
||||
|
||||
signal ctc_counter_2_we : std_logic;
|
||||
-- signal ctc_counter_2_trg : std_logic;
|
||||
signal ctc_counter_2_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_2_int : std_logic;
|
||||
|
||||
signal ctc_counter_3_we : std_logic;
|
||||
signal ctc_counter_3_trg : std_logic;
|
||||
signal ctc_counter_3_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_3_int : std_logic;
|
||||
|
||||
-- signal cpu_rom_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
|
||||
signal wram_we : std_logic;
|
||||
signal wram_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
@ -413,6 +397,10 @@ begin
|
||||
else
|
||||
vs_cnt <= vs_cnt +1;
|
||||
end if;
|
||||
|
||||
if vcnt = 240 then video_vs <= '0'; end if;
|
||||
if vcnt = 242 then video_vs <= '1'; end if;
|
||||
|
||||
else
|
||||
hs_cnt <= hs_cnt + 1;
|
||||
end if;
|
||||
@ -422,8 +410,8 @@ begin
|
||||
vcnt >= 1 and vcnt < 241 then video_blankn <= '1';end if;
|
||||
|
||||
|
||||
if hs_cnt = 0 then hsync0 <= '0';
|
||||
elsif hs_cnt = 47 then hsync0 <= '1';
|
||||
if hs_cnt = 0 then hsync0 <= '0'; video_hs <= '0';
|
||||
elsif hs_cnt = 47 then hsync0 <= '1'; video_hs <= '1';
|
||||
end if;
|
||||
|
||||
if hs_cnt = 0 then hsync1 <= '0';
|
||||
@ -492,24 +480,16 @@ cpu_di <= cpu_rom_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12) < X"7"
|
||||
wram_do when cpu_mreq_n = '0' and cpu_addr(15 downto 12) = X"7" else -- 7000-7FFF
|
||||
sp_ram_cache_do when cpu_mreq_n = '0' and cpu_addr(15 downto 9) = "1111000" else -- sprite ram 0xF000-0xF1FF
|
||||
bg_ram_do when cpu_mreq_n = '0' and cpu_addr(15 downto 10) = "111111" else -- video ram 0xFC00-0xFFFF
|
||||
ctc_controler_do when cpu_ioreq_n = '0' and cpu_m1_n = '0' else -- ctc ctrl (interrupt vector)
|
||||
ctc_do when cpu_int_ack_n = '0' or ctc_ce = '1' else -- ctc (interrupt vector or counter data)
|
||||
ssio_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 4) = X"0" else
|
||||
ctc_counter_3_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F3" else
|
||||
ctc_counter_2_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F2" else
|
||||
ctc_counter_1_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F1" else
|
||||
ctc_counter_0_do when cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else
|
||||
X"FF";
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Misc registers : ctc write enable / interrupt acknowledge
|
||||
------------------------------------------------------------------------
|
||||
ctc_counter_3_trg <= '1' when (vcnt = 246 and tv15Khz_mode = '1') or (vcnt = 493 and tv15Khz_mode = '0')else '0';
|
||||
ctc_counter_3_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F3" else '0';
|
||||
ctc_counter_2_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F2" else '0';
|
||||
ctc_counter_1_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F1" else '0';
|
||||
ctc_counter_0_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else '0';
|
||||
ctc_controler_we <= '1' when cpu_wr_n = '0' and cpu_ioreq_n = '0' and cpu_addr(7 downto 0) = X"F0" else '0'; -- only channel 0 receive int vector
|
||||
ctc_int_ack <= '1' when cpu_ioreq_n = '0' and cpu_m1_n = '0' else '0';
|
||||
cpu_int_ack_n <= cpu_ioreq_n or cpu_m1_n;
|
||||
ctc_ce <= '1' when cpu_ioreq_n = '0' and cpu_addr(7 downto 4) = x"F" else '0';
|
||||
ctc_counter_3_trg <= '1' when top_frame = '1' and ((vcnt = 246 and tv15Khz_mode = '1') or (vcnt = 493 and tv15Khz_mode = '0')) else '0';
|
||||
|
||||
------------------------------------------
|
||||
-- write enable / ram access from CPU --
|
||||
@ -706,92 +686,28 @@ port map(
|
||||
DO => cpu_do
|
||||
);
|
||||
|
||||
-- CTC interrupt controler Z80-CTC (MK3882)
|
||||
ctc_controler : entity work.ctc_controler
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_controler_we,
|
||||
int_ack => ctc_int_ack,
|
||||
|
||||
int_pulse_0 => ctc_counter_0_int,
|
||||
int_pulse_1 => ctc_counter_1_int,
|
||||
int_pulse_2 => ctc_counter_2_int,
|
||||
int_pulse_3 => ctc_counter_3_int,
|
||||
|
||||
d_out => ctc_controler_do,
|
||||
int_n => cpu_irq_n
|
||||
);
|
||||
|
||||
ctc_counter_0 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_0_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_0_do,
|
||||
zc_to => open, -- zc/to #0 (pin 7) connected to clk_trg #1 (pin 22) on schematics (seems to be not used)
|
||||
int_pulse => ctc_counter_0_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_1 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_1_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_1_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_1_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_2 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_2_we,
|
||||
|
||||
clk_trg => '0',
|
||||
|
||||
d_out => ctc_counter_2_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_2_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_3 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => cpu_do,
|
||||
load_data => ctc_counter_3_we,
|
||||
|
||||
clk_trg => ctc_counter_3_trg,
|
||||
|
||||
d_out => ctc_counter_3_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_3_int
|
||||
|
||||
-- Z80-CTC (MK3882)
|
||||
z80ctc : entity work.z80ctc_top
|
||||
port map (
|
||||
clock => clock_vid,
|
||||
clock_ena => cpu_ena,
|
||||
reset => reset,
|
||||
din => cpu_do,
|
||||
cpu_din => cpu_di,
|
||||
dout => ctc_do,
|
||||
ce_n => not ctc_ce,
|
||||
cs => cpu_addr(1 downto 0),
|
||||
m1_n => cpu_m1_n,
|
||||
iorq_n => cpu_ioreq_n,
|
||||
rd_n => cpu_rd_n,
|
||||
int_n => cpu_irq_n,
|
||||
trg0 => '0',
|
||||
to0 => ctc_counter_1_trg,
|
||||
trg1 => ctc_counter_1_trg,
|
||||
to1 => open,
|
||||
trg2 => '0',
|
||||
to2 => open,
|
||||
trg3 => ctc_counter_3_trg
|
||||
);
|
||||
|
||||
-- cpu program ROM 0x0000-0x6FFF
|
||||
|
||||
@ -12,11 +12,12 @@ port(
|
||||
clock : in std_logic;
|
||||
clock_ena : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
|
||||
d_in : in std_logic_vector( 7 downto 0);
|
||||
load_data : in std_logic;
|
||||
int_ack : in std_logic;
|
||||
|
||||
int_end : in std_logic; -- RETI detected
|
||||
|
||||
int_pulse_0 : in std_logic;
|
||||
int_pulse_1 : in std_logic;
|
||||
int_pulse_2 : in std_logic;
|
||||
@ -24,14 +25,13 @@ port(
|
||||
|
||||
d_out : out std_logic_vector( 7 downto 0);
|
||||
int_n : out std_logic
|
||||
|
||||
);
|
||||
end ctc_controler;
|
||||
|
||||
architecture struct of ctc_controler is
|
||||
|
||||
signal int_vector : std_logic_vector(4 downto 0);
|
||||
|
||||
|
||||
signal wait_for_time_constant : std_logic;
|
||||
signal load_data_r : std_logic; -- make sure load_data toggles to get one new data
|
||||
|
||||
@ -39,18 +39,21 @@ architecture struct of ctc_controler is
|
||||
signal int_reg_1 : std_logic;
|
||||
signal int_reg_2 : std_logic;
|
||||
signal int_reg_3 : std_logic;
|
||||
|
||||
|
||||
signal int_in_service : std_logic_vector(3 downto 0);
|
||||
|
||||
signal int_ack_r : std_logic;
|
||||
signal int_end_r : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
int_n <= '0' when (int_reg_0 or int_reg_1 or int_reg_2 or int_reg_3) = '1' else '1';
|
||||
|
||||
d_out <= int_vector & "000" when int_reg_0 = '1' else
|
||||
int_vector & "010" when int_reg_1 = '1' else
|
||||
int_vector & "100" when int_reg_2 = '1' else
|
||||
int_vector & "110" when int_reg_3 = '1' else (others => '0');
|
||||
|
||||
|
||||
process (reset, clock)
|
||||
begin
|
||||
|
||||
@ -60,17 +63,19 @@ begin
|
||||
int_reg_1 <= '0';
|
||||
int_reg_2 <= '0';
|
||||
int_reg_3 <= '0';
|
||||
load_data_r <= load_data;
|
||||
int_in_service <= (others => '0');
|
||||
load_data_r <= '0';
|
||||
int_vector <= (others => '0');
|
||||
else
|
||||
else
|
||||
if rising_edge(clock) then
|
||||
if clock_ena = '1' then
|
||||
|
||||
|
||||
load_data_r <= load_data;
|
||||
int_ack_r <= int_ack;
|
||||
|
||||
int_end_r <= int_end;
|
||||
|
||||
if load_data = '1' and load_data_r = '0' then
|
||||
|
||||
|
||||
if wait_for_time_constant = '1' then
|
||||
wait_for_time_constant <= '0';
|
||||
else
|
||||
@ -78,26 +83,35 @@ begin
|
||||
wait_for_time_constant <= d_in(2);
|
||||
-- if d_in(1) = '1' then -- software reset
|
||||
-- wait_for_time_constant <= '0';
|
||||
-- end if;
|
||||
-- end if;
|
||||
else -- its an interrupt vector
|
||||
int_vector <= d_in(7 downto 3);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
if int_pulse_0 = '1' then int_reg_0 <= '1'; end if;
|
||||
if int_pulse_1 = '1' then int_reg_1 <= '1'; end if;
|
||||
if int_pulse_2 = '1' then int_reg_2 <= '1'; end if;
|
||||
if int_pulse_3 = '1' then int_reg_3 <= '1'; end if;
|
||||
|
||||
if int_ack_r = '1' and int_ack = '0' then
|
||||
if int_reg_0 = '1' then int_reg_0 <= '0';
|
||||
elsif int_reg_1 = '1' then int_reg_1 <= '0';
|
||||
elsif int_reg_2 = '1' then int_reg_2 <= '0';
|
||||
elsif int_reg_3 = '1' then int_reg_3 <= '0'; end if;
|
||||
if int_pulse_0 = '1' and int_in_service(0) = '0' then int_reg_0 <= '1'; end if;
|
||||
if int_pulse_1 = '1' and int_in_service(1 downto 0) = "00" then int_reg_1 <= '1'; end if;
|
||||
if int_pulse_2 = '1' and int_in_service(2 downto 0) = "000" then int_reg_2 <= '1'; end if;
|
||||
if int_pulse_3 = '1' and int_in_service(3 downto 0) = "0000" then int_reg_3 <= '1'; end if;
|
||||
|
||||
if int_ack_r = '0' and int_ack = '1' then
|
||||
if int_reg_0 = '1' then int_reg_0 <= '0'; int_in_service(0) <= '1';
|
||||
elsif int_reg_1 = '1' then int_reg_1 <= '0'; int_in_service(1) <= '1';
|
||||
elsif int_reg_2 = '1' then int_reg_2 <= '0'; int_in_service(2) <= '1';
|
||||
elsif int_reg_3 = '1' then int_reg_3 <= '0'; int_in_service(3) <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
if int_end_r = '0' and int_end = '1' then
|
||||
if int_in_service(0) = '1' then int_in_service(0) <= '0';
|
||||
elsif int_in_service(1) = '1' then int_in_service(1) <= '0';
|
||||
elsif int_in_service(2) = '1' then int_in_service(2) <= '0';
|
||||
elsif int_in_service(3) = '1' then int_in_service(3) <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
@ -12,16 +12,16 @@ port(
|
||||
clock : in std_logic;
|
||||
clock_ena : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
|
||||
d_in : in std_logic_vector( 7 downto 0);
|
||||
load_data : in std_logic;
|
||||
|
||||
clk_trg : in std_logic;
|
||||
|
||||
|
||||
clk_trg : in std_logic;
|
||||
|
||||
d_out : out std_logic_vector(7 downto 0);
|
||||
zc_to : out std_logic;
|
||||
int_pulse : out std_logic
|
||||
|
||||
|
||||
);
|
||||
end ctc_counter;
|
||||
|
||||
@ -35,30 +35,30 @@ architecture struct of ctc_counter is
|
||||
|
||||
signal prescale_max : std_logic_vector(7 downto 0);
|
||||
signal prescale_in : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal count_max : std_logic_vector(8 downto 0);
|
||||
signal count_in : std_logic_vector(8 downto 0) := (others => '0');
|
||||
signal count_max : std_logic_vector(7 downto 0);
|
||||
signal count_in : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal zc_to_in : std_logic;
|
||||
signal clk_trg_in : std_logic;
|
||||
signal clk_trg_r : std_logic;
|
||||
signal trigger : std_logic;
|
||||
signal count_ena : std_logic;
|
||||
signal load_data_r : std_logic; -- make sure load_data toggles to get one new data
|
||||
|
||||
|
||||
begin
|
||||
|
||||
prescale_max <=
|
||||
(others => '0') when control_word(6) = '1' else -- counter mode (prescale max = 0)
|
||||
X"0F" when control_word(6 downto 5) = "00" else -- timer mode prescale 16
|
||||
X"FF"; -- timer mode prescale 256
|
||||
|
||||
trigger <=
|
||||
'1' when (clk_trg = '0' and clk_trg_r = '1' and control_word(4) = '0') or -- falling edge
|
||||
(clk_trg = '1' and clk_trg_r = '0' and control_word(4) = '1') else '0'; -- rising edge
|
||||
|
||||
|
||||
clk_trg_in <= clk_trg xor control_word(4);
|
||||
trigger <= '1' when clk_trg_in = '0' and clk_trg_r = '1' else '0';
|
||||
|
||||
d_out <= count_in(7 downto 0);
|
||||
|
||||
zc_to <= zc_to_in;
|
||||
int_pulse <= zc_to_in when control_word(7) = '1' else '0';
|
||||
|
||||
|
||||
process (reset, clock)
|
||||
begin
|
||||
|
||||
@ -70,34 +70,29 @@ begin
|
||||
restart_on_next_trigger <= '0';
|
||||
count_in <= (others=> '0');
|
||||
zc_to_in <= '0';
|
||||
clk_trg_r <= clk_trg;
|
||||
else
|
||||
clk_trg_r <= '0';
|
||||
else
|
||||
if rising_edge(clock) then
|
||||
if clock_ena = '1' then
|
||||
|
||||
clk_trg_r <= clk_trg;
|
||||
clk_trg_r <= clk_trg_in;
|
||||
load_data_r <= load_data;
|
||||
|
||||
if (restart_on_next_trigger = '1' and trigger = '1') or (restart_on_next_clock = '1') then
|
||||
|
||||
if (restart_on_next_trigger = '1' and trigger = '1') or (restart_on_next_clock = '1') then
|
||||
restart_on_next_clock <= '0';
|
||||
restart_on_next_trigger <= '0';
|
||||
count_ena <= '1';
|
||||
count_in <= count_max;
|
||||
prescale_in <= prescale_max;
|
||||
end if;
|
||||
|
||||
|
||||
if load_data = '1' and load_data_r = '0' then
|
||||
|
||||
if wait_for_time_constant = '1' then
|
||||
wait_for_time_constant <= '0';
|
||||
time_constant_loaded <= '1';
|
||||
|
||||
if d_in = X"00" then
|
||||
count_max <= '1'&X"00";
|
||||
else
|
||||
count_max <= '0'&d_in;
|
||||
end if;
|
||||
|
||||
count_max <= d_in;
|
||||
|
||||
if control_word(6) = '0' and count_ena = '0' then -- in timer mode, if count was stooped
|
||||
if control_word(3) = '0' then -- auto start when time_constant loaded
|
||||
restart_on_next_clock <= '1';
|
||||
@ -105,15 +100,19 @@ begin
|
||||
restart_on_next_trigger <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if control_word(6) = '1' then -- in trigger mode reload the counter immediately,
|
||||
-- otherwise the first period will undefined
|
||||
prescale_in <= (others => '0');
|
||||
count_in <= d_in;
|
||||
end if;
|
||||
else -- not waiting for time constant
|
||||
|
||||
|
||||
if d_in(0) = '1' then -- check if its a control world
|
||||
control_word <= d_in;
|
||||
wait_for_time_constant <= d_in(2);
|
||||
restart_on_next_clock <= '0';
|
||||
restart_on_next_trigger <= '0';
|
||||
|
||||
|
||||
if d_in(1) = '1' then -- software reset
|
||||
count_ena <= '0';
|
||||
time_constant_loaded <= '0';
|
||||
@ -122,28 +121,28 @@ begin
|
||||
clk_trg_r <= clk_trg;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
end if;
|
||||
|
||||
|
||||
end if; -- end load data
|
||||
|
||||
|
||||
-- counter
|
||||
zc_to_in <= '0';
|
||||
if ((control_word(6) = '1' and trigger = '1' ) or
|
||||
(control_word(6) = '0' and count_ena = '1') ) and time_constant_loaded = '1' then
|
||||
(control_word(6) = '0' and count_ena = '1') ) and time_constant_loaded = '1' then
|
||||
if prescale_in = 0 then
|
||||
prescale_in <= '0'&prescale_max(7 downto 1); -- test divide by 2 !
|
||||
if count_in = 0 then
|
||||
prescale_in <= prescale_max;
|
||||
if count_in = 1 then
|
||||
zc_to_in <= '1';
|
||||
count_in <= count_max;
|
||||
else
|
||||
count_in <= count_in - '1';
|
||||
count_in <= count_in - '1';
|
||||
end if;
|
||||
else
|
||||
prescale_in <= prescale_in - '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
4
common/IO/Z80CTC/z80ctc.qip
Normal file
4
common/IO/Z80CTC/z80ctc.qip
Normal file
@ -0,0 +1,4 @@
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) z80ctc_top.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ctc_controler.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ctc_counter.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) z80ctc_top.vhd ]
|
||||
185
common/IO/Z80CTC/z80ctc_top.vhd
Normal file
185
common/IO/Z80CTC/z80ctc_top.vhd
Normal file
@ -0,0 +1,185 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
-- Z80-CTC (MK3882) top-level
|
||||
entity z80ctc_top is
|
||||
port(
|
||||
clock : in std_logic;
|
||||
clock_ena : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
din : in std_logic_vector(7 downto 0);
|
||||
dout : out std_logic_vector(7 downto 0);
|
||||
cpu_din : in std_logic_vector(7 downto 0); -- mirror the input to the cpu, for RETI detection
|
||||
|
||||
ce_n : in std_logic;
|
||||
cs : in std_logic_vector(1 downto 0);
|
||||
m1_n : in std_logic;
|
||||
iorq_n : in std_logic;
|
||||
rd_n : in std_logic;
|
||||
int_n : out std_logic;
|
||||
|
||||
trg0 : in std_logic;
|
||||
to0 : out std_logic;
|
||||
|
||||
trg1 : in std_logic;
|
||||
to1 : out std_logic;
|
||||
|
||||
trg2 : in std_logic;
|
||||
to2 : out std_logic;
|
||||
|
||||
trg3 : in std_logic
|
||||
);
|
||||
end z80ctc_top;
|
||||
|
||||
architecture struct of z80ctc_top is
|
||||
|
||||
signal cpu_int_ack_n : std_logic;
|
||||
|
||||
signal ctc_controler_we : std_logic;
|
||||
signal ctc_controler_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_int_ack : std_logic;
|
||||
signal ctc_int_ack_phase : std_logic_vector(1 downto 0);
|
||||
|
||||
signal ctc_counter_0_we : std_logic;
|
||||
signal ctc_counter_0_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_0_int : std_logic;
|
||||
|
||||
signal ctc_counter_1_we : std_logic;
|
||||
signal ctc_counter_1_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_1_int : std_logic;
|
||||
|
||||
signal ctc_counter_2_we : std_logic;
|
||||
signal ctc_counter_2_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_2_int : std_logic;
|
||||
|
||||
signal ctc_counter_3_we : std_logic;
|
||||
signal ctc_counter_3_do : std_logic_vector(7 downto 0);
|
||||
signal ctc_counter_3_int : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
process (clock, reset)
|
||||
begin
|
||||
if reset = '1' then
|
||||
ctc_int_ack_phase <= "00";
|
||||
elsif rising_edge(clock) then
|
||||
-- decode ED4D (reti)
|
||||
if clock_ena = '1' and rd_n = '0' and m1_n = '0' then
|
||||
case ctc_int_ack_phase is
|
||||
when "00" => if cpu_din = x"ED" then ctc_int_ack_phase <= "01"; end if;
|
||||
when "01" => if cpu_din = x"4D" then ctc_int_ack_phase <= "11"; elsif cpu_din /= x"ED" then ctc_int_ack_phase <= "00"; end if;
|
||||
when "11" => if cpu_din = x"ED" then ctc_int_ack_phase <= "01"; elsif cpu_din /= x"4D" then ctc_int_ack_phase <= "00"; end if;
|
||||
when others => ctc_int_ack_phase <= "00";
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ctc_int_ack <= '1' when ctc_int_ack_phase = "11" else '0';
|
||||
cpu_int_ack_n <= iorq_n or m1_n;
|
||||
|
||||
ctc_controler_we <= '1' when ce_n = '0' and iorq_n = '0' and m1_n = '1' and rd_n = '1' and cs = "00" else '0';
|
||||
ctc_counter_0_we <= '1' when ce_n = '0' and iorq_n = '0' and m1_n = '1' and rd_n = '1' and cs = "00" else '0';
|
||||
ctc_counter_1_we <= '1' when ce_n = '0' and iorq_n = '0' and m1_n = '1' and rd_n = '1' and cs = "01" else '0';
|
||||
ctc_counter_2_we <= '1' when ce_n = '0' and iorq_n = '0' and m1_n = '1' and rd_n = '1' and cs = "10" else '0';
|
||||
ctc_counter_3_we <= '1' when ce_n = '0' and iorq_n = '0' and m1_n = '1' and rd_n = '1' and cs = "11" else '0';
|
||||
|
||||
dout <= ctc_controler_do when cpu_int_ack_n = '0' else
|
||||
ctc_counter_0_do when iorq_n = '0' and m1_n = '1' and rd_n = '0' and cs = "00" else
|
||||
ctc_counter_1_do when iorq_n = '0' and m1_n = '1' and rd_n = '0' and cs = "01" else
|
||||
ctc_counter_2_do when iorq_n = '0' and m1_n = '1' and rd_n = '0' and cs = "10" else
|
||||
ctc_counter_3_do when iorq_n = '0' and m1_n = '1' and rd_n = '0' and cs = "11" else
|
||||
x"FF";
|
||||
|
||||
-- CTC interrupt controler Z80-CTC (MK3882)
|
||||
ctc_controler : entity work.ctc_controler
|
||||
port map(
|
||||
clock => clock,
|
||||
clock_ena => clock_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => din,
|
||||
load_data => ctc_controler_we,
|
||||
int_ack => cpu_int_ack_n,
|
||||
int_end => ctc_int_ack,
|
||||
|
||||
int_pulse_0 => ctc_counter_0_int,
|
||||
int_pulse_1 => ctc_counter_1_int,
|
||||
int_pulse_2 => ctc_counter_2_int,
|
||||
int_pulse_3 => ctc_counter_3_int,
|
||||
|
||||
d_out => ctc_controler_do,
|
||||
int_n => int_n
|
||||
);
|
||||
|
||||
ctc_counter_0 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock,
|
||||
clock_ena => clock_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => din,
|
||||
load_data => ctc_counter_0_we,
|
||||
|
||||
clk_trg => trg0,
|
||||
|
||||
d_out => ctc_counter_0_do,
|
||||
zc_to => to0,
|
||||
int_pulse => ctc_counter_0_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_1 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock,
|
||||
clock_ena => clock_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => din,
|
||||
load_data => ctc_counter_1_we,
|
||||
|
||||
clk_trg => trg1,
|
||||
|
||||
d_out => ctc_counter_1_do,
|
||||
zc_to => to1,
|
||||
int_pulse => ctc_counter_1_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_2 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock,
|
||||
clock_ena => clock_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => din,
|
||||
load_data => ctc_counter_2_we,
|
||||
|
||||
clk_trg => trg2,
|
||||
|
||||
d_out => ctc_counter_2_do,
|
||||
zc_to => to2,
|
||||
int_pulse => ctc_counter_2_int
|
||||
|
||||
);
|
||||
|
||||
ctc_counter_3 : entity work.ctc_counter
|
||||
port map(
|
||||
clock => clock,
|
||||
clock_ena => clock_ena,
|
||||
reset => reset,
|
||||
|
||||
d_in => din,
|
||||
load_data => ctc_counter_3_we,
|
||||
|
||||
clk_trg => trg3,
|
||||
|
||||
d_out => ctc_counter_3_do,
|
||||
zc_to => open,
|
||||
int_pulse => ctc_counter_3_int
|
||||
|
||||
);
|
||||
end struct;
|
||||
Loading…
x
Reference in New Issue
Block a user