mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-19 17:27:59 +00:00
MCR3 Monoboard: use common CTC and inputs
This commit is contained in:
parent
45697c5ce6
commit
e90e339a8e
@ -41,7 +41,7 @@
|
||||
# ========================
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
|
||||
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
||||
|
||||
# Pin & Location Assignments
|
||||
@ -212,8 +212,6 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/MCR3Mono_MiST.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/spinner.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/mcr3mono.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/gen_ram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/cmos_ram.vhd
|
||||
@ -221,7 +219,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
|
||||
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/sounds_good.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/turbo_cheap_squeak.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/z80ctc_top.vhd
|
||||
set_global_assignment -name QIP_FILE ../../common/IO/Z80CTC/z80ctc.qip
|
||||
set_global_assignment -name QIP_FILE ../../common/CPU/68000/FX68k/fx68k.qip
|
||||
set_global_assignment -name VHDL_FILE ../../common/IO/pia6821.vhd
|
||||
set_global_assignment -name VHDL_FILE ../../common/CPU/MC6809/cpu09l_128a.vhd
|
||||
|
||||
@ -79,24 +79,24 @@ always @(*) begin
|
||||
|
||||
if (`CORE_NAME == "SARGE") begin
|
||||
// Two stick/player like the original
|
||||
input0 = ~{2'b00, service, 1'b0, m_start2, m_start1, m_coin2, m_coin1};
|
||||
input1 = ~{m_fire1 | m_fire1b, m_fire1 | m_fire1b, m_fire2 | m_fire2b, m_fire2 | m_fire2b, m_down1, m_up1, m_down2, m_up2};
|
||||
input2 = ~{m_fire3 | m_fire3b, m_fire3 | m_fire3b, m_fire4 | m_fire4b, m_fire4 | m_fire4b, m_down3, m_up3, m_down4, m_up4};
|
||||
input0 = ~{2'b00, service, 1'b0, m_two_players, m_one_player, m_coin2, m_coin1};
|
||||
input1 = ~{m_fireA | m_fireB, m_fireA | m_fireB, m_fire2A | m_fire2B, m_fire2A | m_fire2B, m_down, m_up, m_down, m_up};
|
||||
input2 = ~{m_fire3A | m_fire3B, m_fire3A | m_fire3B, m_fire4A | m_fire4B, m_fire4A | m_fire4B, m_down3, m_up3, m_down4, m_up4};
|
||||
end else if (`CORE_NAME == "MAXRPM") begin
|
||||
input0 = ~{service, 3'b000, m_start1, m_start2, m_coin1, m_coin2};
|
||||
input0 = ~{service, 3'b000, m_one_player, m_two_players, m_coin1, m_coin2};
|
||||
input1 = {pedal1[5:2], pedal2[5:2]};
|
||||
input2 = ~{maxrpm_gear1, maxrpm_gear2};
|
||||
end else if (`CORE_NAME == "RAMPAGE") begin
|
||||
// normal controls for 3 players
|
||||
input0 = ~{2'b00, service, 1'b0, 2'b00, m_coin2, m_coin1};
|
||||
input1 = ~{2'b00, m_fire1b, m_fire1, m_left1, m_down1, m_right1, m_up1};
|
||||
input2 = ~{2'b00, m_fire2b, m_fire2, m_left2, m_down2, m_right2, m_up2};
|
||||
input4 = ~{2'b00, m_fire3b, m_fire3, m_left3, m_down3, m_right3, m_up3};
|
||||
input1 = ~{2'b00, m_fireB, m_fireA, m_left, m_down, m_right, m_up};
|
||||
input2 = ~{2'b00, m_fire2B, m_fire2A, m_left2, m_down2, m_right2, m_up2};
|
||||
input4 = ~{2'b00, m_fire3B, m_fire3A, m_left3, m_down3, m_right3, m_up3};
|
||||
end else if (`CORE_NAME == "POWERDRV") begin
|
||||
// Controls for 3 players using 4 buttons/joystick
|
||||
input0 = ~{2'b00, service, 1'b0, 1'b0, m_coin3, m_coin2, m_coin1};
|
||||
input1 = ~{m_fire2b, m_fire2, powerdrv_gear[1], m_fire2c, m_fire1b, m_fire1, powerdrv_gear[0], m_fire1c};
|
||||
input2 = ~{sndstat[0], 3'b000, m_fire3b, m_fire3, powerdrv_gear[2], m_fire3c};
|
||||
input1 = ~{m_fire2B, m_fire2A, powerdrv_gear[1], m_fire2C, m_fireB, m_fireA, powerdrv_gear[0], m_fireC};
|
||||
input2 = ~{sndstat[0], 3'b000, m_fire3B, m_fire3A, powerdrv_gear[2], m_fire3C};
|
||||
end
|
||||
end
|
||||
|
||||
@ -110,6 +110,7 @@ localparam CONF_STR = {
|
||||
"V,v1.1.",`BUILD_DATE
|
||||
};
|
||||
|
||||
wire rotate = status[2];
|
||||
wire blend = status[5];
|
||||
wire joyswap = status[6];
|
||||
wire service = status[7];
|
||||
@ -131,16 +132,19 @@ pll_mist pll(
|
||||
wire [31:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
wire [7:0] joy_0;
|
||||
wire [7:0] joy_1;
|
||||
wire [7:0] joy_2;
|
||||
wire [7:0] joy_3;
|
||||
wire [7:0] joystick_0;
|
||||
wire [7:0] joystick_1;
|
||||
wire [7:0] joystick_2;
|
||||
wire [7:0] joystick_3;
|
||||
wire scandoublerD;
|
||||
wire ypbpr;
|
||||
wire [9:0] audio;
|
||||
wire hs, vs, cs;
|
||||
wire blankn;
|
||||
wire [2:0] g, r, b;
|
||||
wire key_pressed;
|
||||
wire [7:0] key_code;
|
||||
wire key_strobe;
|
||||
|
||||
wire ioctl_downl;
|
||||
wire [7:0] ioctl_index;
|
||||
@ -332,7 +336,7 @@ mist_video #(.COLOR_DEPTH(3)) 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 ( blend ),
|
||||
.scandoubler_disable(1),//scandoublerD ),
|
||||
@ -356,10 +360,10 @@ user_io(
|
||||
.key_strobe (key_strobe ),
|
||||
.key_pressed (key_pressed ),
|
||||
.key_code (key_code ),
|
||||
.joystick_0 (joy_0 ),
|
||||
.joystick_1 (joy_1 ),
|
||||
.joystick_2 (joy_2 ),
|
||||
.joystick_3 (joy_3 ),
|
||||
.joystick_0 (joystick_0 ),
|
||||
.joystick_1 (joystick_1 ),
|
||||
.joystick_2 (joystick_2 ),
|
||||
.joystick_3 (joystick_3 ),
|
||||
.status (status )
|
||||
);
|
||||
|
||||
@ -371,19 +375,16 @@ dac #(10) dac(
|
||||
);
|
||||
assign AUDIO_R = AUDIO_L;
|
||||
|
||||
wire [7:0] joystick_0 = joyswap ? joy_1 : joy_0;
|
||||
wire [7:0] joystick_1 = joyswap ? joy_0 : joy_1;
|
||||
|
||||
// Power Drive gear
|
||||
reg [2:0] powerdrv_gear;
|
||||
always @(posedge clk_sys) begin
|
||||
reg [2:0] gear_old;
|
||||
if (reset) powerdrv_gear <= 0;
|
||||
else begin
|
||||
gear_old <= {m_fire3d, m_fire2d, m_fire1d};
|
||||
if (~gear_old[0] & m_fire1d) powerdrv_gear[0] <= ~powerdrv_gear[0];
|
||||
if (~gear_old[1] & m_fire2d) powerdrv_gear[1] <= ~powerdrv_gear[1];
|
||||
if (~gear_old[2] & m_fire3d) powerdrv_gear[2] <= ~powerdrv_gear[2];
|
||||
gear_old <= {m_fire3D, m_fire2D, m_fireD};
|
||||
if (~gear_old[0] & m_fireD) powerdrv_gear[0] <= ~powerdrv_gear[0];
|
||||
if (~gear_old[1] & m_fire2D) powerdrv_gear[1] <= ~powerdrv_gear[1];
|
||||
if (~gear_old[2] & m_fire3D) powerdrv_gear[2] <= ~powerdrv_gear[2];
|
||||
end
|
||||
end
|
||||
|
||||
@ -393,8 +394,8 @@ spinner spinner1 (
|
||||
.clock_40(clk_sys),
|
||||
.reset(reset),
|
||||
.btn_acc(),
|
||||
.btn_left(m_up1),
|
||||
.btn_right(m_down1),
|
||||
.btn_left(m_up),
|
||||
.btn_right(m_down),
|
||||
.ctc_zc_to_2(vs),
|
||||
.spin_angle(pedal1)
|
||||
);
|
||||
@ -417,140 +418,52 @@ wire [3:0] maxrpm_gear2 = maxrpm_gear_bits[gear2];
|
||||
reg [2:0] gear1;
|
||||
reg [2:0] gear2;
|
||||
always @(posedge clk_sys) begin
|
||||
reg m_fire1_last, m_fire1b_last;
|
||||
reg m_fire2_last, m_fire2b_last;
|
||||
reg m_fireA_last, m_fireB_last;
|
||||
reg m_fire2A_last, m_fire2B_last;
|
||||
|
||||
if (reset) begin
|
||||
gear1 <= 0;
|
||||
gear2 <= 0;
|
||||
end else begin
|
||||
m_fire1_last <= m_fire1;
|
||||
m_fire1b_last <= m_fire1b;
|
||||
m_fire2_last <= m_fire2;
|
||||
m_fire2b_last <= m_fire2b;
|
||||
m_fireA_last <= m_fireA;
|
||||
m_fireB_last <= m_fireB;
|
||||
m_fire2A_last <= m_fire2A;
|
||||
m_fire2B_last <= m_fire2B;
|
||||
|
||||
if (m_start1) gear1 <= 0;
|
||||
else if (~m_fire1_last && m_fire1 && gear1 != 3'd4) gear1 <= gear1 + 1'd1;
|
||||
else if (~m_fire1b_last && m_fire1b && gear1 != 3'd0) gear1 <= gear1 - 1'd1;
|
||||
if (m_one_player) gear1 <= 0;
|
||||
else if (~m_fireA_last && m_fireA && gear1 != 3'd4) gear1 <= gear1 + 1'd1;
|
||||
else if (~m_fireB_last && m_fireB && gear1 != 3'd0) gear1 <= gear1 - 1'd1;
|
||||
|
||||
if (m_start2) gear2 <= 0;
|
||||
else if (~m_fire2_last && m_fire2 && gear2 != 3'd4) gear2 <= gear2 + 1'd1;
|
||||
else if (~m_fire2b_last && m_fire2b && gear2 != 3'd0) gear2 <= gear2 - 1'd1;
|
||||
if (m_two_players) gear2 <= 0;
|
||||
else if (~m_fire2A_last && m_fire2A && gear2 != 3'd4) gear2 <= gear2 + 1'd1;
|
||||
else if (~m_fire2B_last && m_fire2B && gear2 != 3'd0) gear2 <= gear2 - 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// Generic controls - make a module from this?
|
||||
wire m_coin1 = btn_coin1_mame | btn_coin;
|
||||
wire m_start1 = btn_start1_mame | btn_one_player;
|
||||
wire m_up1 = btn_up | joystick_0[3];
|
||||
wire m_down1 = btn_down | joystick_0[2];
|
||||
wire m_left1 = btn_left | joystick_0[1];
|
||||
wire m_right1 = btn_right | joystick_0[0];
|
||||
wire m_fire1 = btn_fireA | joystick_0[4];
|
||||
wire m_fire1b = btn_fireB | joystick_0[5];
|
||||
wire m_fire1c = btn_fireC | joystick_0[6];
|
||||
wire m_fire1d = btn_fireD | joystick_0[7];
|
||||
wire m_up, m_down, m_left, m_right, m_fireA, m_fireB, m_fireC, m_fireD;
|
||||
wire m_up2, m_down2, m_left2, m_right2, m_fire2A, m_fire2B, m_fire2C, m_fire2D;
|
||||
wire m_up3, m_down3, m_left3, m_right3, m_fire3A, m_fire3B, m_fire3C, m_fire3D;
|
||||
wire m_up4, m_down4, m_left4, m_right4, m_fire4A, m_fire4B, m_fire4C, m_fire4D;
|
||||
wire m_tilt, m_coin1, m_coin2, m_coin3, m_coin4, m_one_player, m_two_players, m_three_players, m_four_players;
|
||||
|
||||
wire m_coin2 = btn_coin2_mame | btn_coin;
|
||||
wire m_start2 = btn_start2_mame | btn_two_players;
|
||||
wire m_left2 = btn_left2 | joystick_1[1];
|
||||
wire m_right2 = btn_right2 | joystick_1[0];
|
||||
wire m_up2 = btn_up2 | joystick_1[3];
|
||||
wire m_down2 = btn_down2 | joystick_1[2];
|
||||
wire m_fire2 = btn_fire2A | joystick_1[4];
|
||||
wire m_fire2b = btn_fire2B | joystick_1[5];
|
||||
wire m_fire2c = btn_fire2C | joystick_1[6];
|
||||
wire m_fire2d = btn_fire2D | joystick_1[7];
|
||||
|
||||
wire m_coin3 = btn_coin3_mame | btn_coin;
|
||||
wire m_start3 = btn_start3_mame | btn_three_players;
|
||||
wire m_left3 = joy_2[1];
|
||||
wire m_right3 = joy_2[0];
|
||||
wire m_up3 = joy_2[3];
|
||||
wire m_down3 = joy_2[2];
|
||||
wire m_fire3 = joy_2[4];
|
||||
wire m_fire3b = joy_2[5];
|
||||
wire m_fire3c = joy_2[6];
|
||||
wire m_fire3d = joy_2[7];
|
||||
|
||||
wire m_coin4 = btn_coin4_mame | btn_coin;
|
||||
wire m_start4 = btn_start4_mame | btn_four_players;
|
||||
wire m_left4 = joy_3[1];
|
||||
wire m_right4 = joy_3[0];
|
||||
wire m_up4 = joy_3[3];
|
||||
wire m_down4 = joy_3[2];
|
||||
wire m_fire4 = joy_3[4];
|
||||
wire m_fire4b = joy_3[5];
|
||||
|
||||
reg btn_one_player = 0;
|
||||
reg btn_two_players = 0;
|
||||
reg btn_three_players = 0;
|
||||
reg btn_four_players = 0;
|
||||
reg btn_left = 0;
|
||||
reg btn_right = 0;
|
||||
reg btn_down = 0;
|
||||
reg btn_up = 0;
|
||||
reg btn_fireA = 0;
|
||||
reg btn_fireB = 0;
|
||||
reg btn_fireC = 0;
|
||||
reg btn_fireD = 0;
|
||||
reg btn_coin = 0;
|
||||
reg btn_start1_mame = 0;
|
||||
reg btn_start2_mame = 0;
|
||||
reg btn_start3_mame = 0;
|
||||
reg btn_start4_mame = 0;
|
||||
reg btn_coin1_mame = 0;
|
||||
reg btn_coin2_mame = 0;
|
||||
reg btn_coin3_mame = 0;
|
||||
reg btn_coin4_mame = 0;
|
||||
reg btn_up2 = 0;
|
||||
reg btn_down2 = 0;
|
||||
reg btn_left2 = 0;
|
||||
reg btn_right2 = 0;
|
||||
reg btn_fire2A = 0;
|
||||
reg btn_fire2B = 0;
|
||||
reg btn_fire2C = 0;
|
||||
reg btn_fire2D = 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
|
||||
'h04: btn_three_players <= key_pressed; // F3
|
||||
'h0C: btn_four_players <= key_pressed; // F4
|
||||
'h12: btn_fireD <= key_pressed; // l-shift
|
||||
'h14: btn_fireC <= key_pressed; // ctrl
|
||||
'h11: btn_fireB <= key_pressed; // alt
|
||||
'h29: btn_fireA <= key_pressed; // Space
|
||||
// JPAC/IPAC/MAME Style Codes
|
||||
'h16: btn_start1_mame <= key_pressed; // 1
|
||||
'h1E: btn_start2_mame <= key_pressed; // 2
|
||||
'h26: btn_start3_mame <= key_pressed; // 3
|
||||
'h25: btn_start4_mame <= key_pressed; // 4
|
||||
'h2E: btn_coin1_mame <= key_pressed; // 5
|
||||
'h36: btn_coin2_mame <= key_pressed; // 6
|
||||
'h3D: btn_coin3_mame <= key_pressed; // 7
|
||||
'h3E: btn_coin4_mame <= key_pressed; // 8
|
||||
'h2D: btn_up2 <= key_pressed; // R
|
||||
'h2B: btn_down2 <= key_pressed; // F
|
||||
'h23: btn_left2 <= key_pressed; // D
|
||||
'h34: btn_right2 <= key_pressed; // G
|
||||
'h1C: btn_fire2A <= key_pressed; // A
|
||||
'h1B: btn_fire2B <= key_pressed; // S
|
||||
'h21: btn_fire2C <= key_pressed; // Q
|
||||
'h1D: btn_fire2D <= key_pressed; // W
|
||||
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 ),
|
||||
.joystick_2 ( joystick_2 ),
|
||||
.joystick_3 ( joystick_3 ),
|
||||
.rotate ( rotate ),
|
||||
.orientation ( 2'b10 ),
|
||||
.joyswap ( joyswap ),
|
||||
.oneplayer ( 1'b0 ),
|
||||
.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_fireD, m_fireC, m_fireB, m_fireA, m_up, m_down, m_left, m_right} ),
|
||||
.player2 ( {m_fire2D, m_fire2C, m_fire2B, m_fire2A, m_up2, m_down2, m_left2, m_right2} ),
|
||||
.player3 ( {m_fire3D, m_fire3C, m_fire3B, m_fire3A, m_up3, m_down3, m_left3, m_right3} ),
|
||||
.player4 ( {m_fire4D, m_fire4C, m_fire4B, m_fire4A, m_up4, m_down4, m_left4, m_right4} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@ -1,120 +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_end : in std_logic; -- RETI detected
|
||||
|
||||
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_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
|
||||
|
||||
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';
|
||||
int_in_service <= (others => '0');
|
||||
load_data_r <= '0';
|
||||
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;
|
||||
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
|
||||
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' 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;
|
||||
end process;
|
||||
|
||||
end struct;
|
||||
@ -1,151 +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(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
|
||||
|
||||
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
|
||||
|
||||
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 <= '0';
|
||||
else
|
||||
if rising_edge(clock) then
|
||||
if clock_ena = '1' then
|
||||
|
||||
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
|
||||
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';
|
||||
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';
|
||||
else -- wait for trigger to start
|
||||
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';
|
||||
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 <= prescale_max;
|
||||
if count_in = 1 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;
|
||||
@ -1,185 +0,0 @@
|
||||
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