mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-04-14 07:29:37 +00:00
Merge pull request #152 from gyurco/master
M72 + ExpressRaider + Druaga fixes
This commit is contained in:
@@ -168,6 +168,7 @@ video u_video(
|
||||
.cpu_ab ( cpu_ab ),
|
||||
.cpu_dout ( cpu_dout ),
|
||||
.rw ( rw ),
|
||||
.dma_swap ( dma_swap ),
|
||||
.sram_data ( sram_data ),
|
||||
.map_rom_addr ( map_rom_addr ),
|
||||
.map_data ( map_data ),
|
||||
|
||||
@@ -12,8 +12,9 @@ module video(
|
||||
input [15:0] cpu_ab,
|
||||
input [7:0] cpu_dout,
|
||||
input rw,
|
||||
input dma_swap,
|
||||
|
||||
output reg [7:0] sram_data,
|
||||
output [7:0] sram_data,
|
||||
|
||||
output [14:0] map_rom_addr,
|
||||
input [7:0] map_data,
|
||||
@@ -52,10 +53,6 @@ wire [7:0] sram1_q;
|
||||
wire [7:0] sram2_q;
|
||||
wire [7:0] sram3_q;
|
||||
wire [7:0] sram4_q;
|
||||
wire [7:0] sram1_dout;
|
||||
wire [7:0] sram2_dout;
|
||||
wire [7:0] sram3_dout;
|
||||
wire [7:0] sram4_dout;
|
||||
|
||||
reg [7:0] scx1; // 10C
|
||||
reg [7:0] scx2; // 11C
|
||||
@@ -96,29 +93,62 @@ dpram #(12,8) u8C(
|
||||
|
||||
// SRAM
|
||||
|
||||
wire sram_wr = sram_cs & ~rw;
|
||||
wire sram1_en = cpu_ab[1:0] == 2'b00;
|
||||
wire sram2_en = cpu_ab[1:0] == 2'b01;
|
||||
wire sram3_en = cpu_ab[1:0] == 2'b10;
|
||||
wire sram4_en = cpu_ab[1:0] == 2'b11;
|
||||
reg [8:0] dma_a;
|
||||
wire [7:0] sram_q;
|
||||
reg dma_wr;
|
||||
|
||||
// must be synced to cpu clock if chip_6502 is used
|
||||
// a typical symptom is the horse with static legs
|
||||
always @(posedge clk_sys)
|
||||
if (rw)
|
||||
sram_data <=
|
||||
sram1_en ? sram1_dout :
|
||||
sram2_en ? sram2_dout :
|
||||
sram3_en ? sram3_dout :
|
||||
sram4_en ? sram4_dout : 8'hff;
|
||||
wire sram_wr = sram_cs & ~rw;
|
||||
wire sram1_en = dma_a[1:0] == 2'b00;
|
||||
wire sram2_en = dma_a[1:0] == 2'b01;
|
||||
wire sram3_en = dma_a[1:0] == 2'b10;
|
||||
wire sram4_en = dma_a[1:0] == 2'b11;
|
||||
|
||||
reg [1:0] dma_state;
|
||||
always @(posedge clk_sys) begin
|
||||
if (reset) begin
|
||||
dma_state <= 0;
|
||||
dma_wr <= 0;
|
||||
end else begin
|
||||
dma_wr <= 0;
|
||||
|
||||
case (dma_state)
|
||||
0: begin
|
||||
dma_a <= 0;
|
||||
if (dma_swap) dma_state <= 1;
|
||||
end
|
||||
1: begin
|
||||
dma_wr <= 1;
|
||||
dma_state <= 2;
|
||||
end
|
||||
2: begin
|
||||
dma_a <= dma_a + 1'd1;
|
||||
if (dma_a == 9'h1FF) dma_state <= 0; // finished
|
||||
else dma_state <= 3;
|
||||
end
|
||||
3: dma_state <= 1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
dpram #(9,8) sram(
|
||||
.clock ( clk_sys ),
|
||||
.address_a ( cpu_ab ),
|
||||
.data_a ( cpu_dout ),
|
||||
.q_a ( sram_data ),
|
||||
.rden_a ( 1'b1 ),
|
||||
.wren_a ( sram_wr ),
|
||||
.address_b ( dma_a ),
|
||||
.rden_b ( 1'b1 ),
|
||||
.q_b ( sram_q )
|
||||
);
|
||||
|
||||
dpram #(7,8) sram1(
|
||||
.clock ( ~clk_sys ),
|
||||
.address_a ( cpu_ab[8:2] ),
|
||||
.data_a ( cpu_dout ),
|
||||
.q_a ( sram1_dout ),
|
||||
.address_a ( dma_a[8:2] ),
|
||||
.data_a ( sram_q ),
|
||||
.q_a ( ),
|
||||
.rden_a ( 1'b1 ),
|
||||
.wren_a ( sram_wr & sram1_en ),
|
||||
.wren_a ( dma_wr & sram1_en ),
|
||||
.address_b ( sram_addr ),
|
||||
.rden_b ( 1'b1 ),
|
||||
.q_b ( sram1_q )
|
||||
@@ -126,11 +156,11 @@ dpram #(7,8) sram1(
|
||||
|
||||
dpram #(7,8) sram2(
|
||||
.clock ( ~clk_sys ),
|
||||
.address_a ( cpu_ab[8:2] ),
|
||||
.data_a ( cpu_dout ),
|
||||
.q_a ( sram2_dout ),
|
||||
.address_a ( dma_a[8:2] ),
|
||||
.data_a ( sram_q ),
|
||||
.q_a ( ),
|
||||
.rden_a ( 1'b1 ),
|
||||
.wren_a ( sram_wr & sram2_en ),
|
||||
.wren_a ( dma_wr & sram2_en ),
|
||||
.address_b ( sram_addr ),
|
||||
.rden_b ( 1'b1 ),
|
||||
.q_b ( sram2_q )
|
||||
@@ -138,11 +168,11 @@ dpram #(7,8) sram2(
|
||||
|
||||
dpram #(7,8) sram3(
|
||||
.clock ( ~clk_sys ),
|
||||
.address_a ( cpu_ab[8:2] ),
|
||||
.data_a ( cpu_dout ),
|
||||
.q_a ( sram3_dout ),
|
||||
.address_a ( dma_a[8:2] ),
|
||||
.data_a ( sram_q ),
|
||||
.q_a ( ),
|
||||
.rden_a ( 1'b1 ),
|
||||
.wren_a ( sram_wr & sram3_en ),
|
||||
.wren_a ( dma_wr & sram3_en ),
|
||||
.address_b ( sram_addr ),
|
||||
.rden_b ( 1'b1 ),
|
||||
.q_b ( sram3_q )
|
||||
@@ -150,11 +180,11 @@ dpram #(7,8) sram3(
|
||||
|
||||
dpram #(7,8) sram4(
|
||||
.clock ( ~clk_sys ),
|
||||
.address_a ( cpu_ab[8:2] ),
|
||||
.data_a ( cpu_dout ),
|
||||
.q_a ( sram4_dout ),
|
||||
.address_a ( dma_a[8:2] ),
|
||||
.data_a ( sram_q ),
|
||||
.q_a ( ),
|
||||
.rden_a ( 1'b1 ),
|
||||
.wren_a ( sram_wr & sram4_en ),
|
||||
.wren_a ( dma_wr & sram4_en ),
|
||||
.address_b ( sram_addr ),
|
||||
.rden_b ( 1'b1 ),
|
||||
.q_b ( sram4_q )
|
||||
@@ -281,7 +311,7 @@ always @(posedge clk_sys) begin
|
||||
sxc <= 0;
|
||||
sp_rom_addr <= { sram2_q[7:5], id, flip, syc[3:0] };
|
||||
next_state <= 2;
|
||||
state <= 3;//7;
|
||||
state <= 3;
|
||||
end
|
||||
else begin
|
||||
sram_addr <= sram_addr + 7'd1;
|
||||
@@ -298,7 +328,7 @@ always @(posedge clk_sys) begin
|
||||
if (sxc == 4'd7) begin
|
||||
sp_rom_addr <= { sram2_q[7:5], id, ~flip, syc[3:0] };
|
||||
next_state <= 2;
|
||||
state <= 3;//7;
|
||||
state <= 3;
|
||||
end
|
||||
else if (sxc == 4'd15) begin
|
||||
sram_addr <= sram_addr + 7'd1;
|
||||
|
||||
@@ -132,7 +132,7 @@ set_global_assignment -name TOP_LEVEL_ENTITY IremM72_MiST
|
||||
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
|
||||
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
|
||||
set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP
|
||||
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED
|
||||
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE BALANCED
|
||||
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON
|
||||
set_global_assignment -name ALLOW_SYNCH_CTRL_USAGE ON
|
||||
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
|
||||
@@ -237,32 +237,12 @@ set_location_assignment PLL_1 -to pll|altpll_component|auto_generated|pll1
|
||||
set_global_assignment -name DSP_BLOCK_BALANCING "DSP BLOCKS"
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF
|
||||
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION OFF
|
||||
set_global_assignment -name AUTO_SHIFT_REGISTER_RECOGNITION AUTO
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA
|
||||
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/IremM72_MiST.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/build_id.v
|
||||
set_global_assignment -name QIP_FILE rtl/pll_mist.qip
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/ddr_debug.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/m72.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/pal.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mcu.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sample_rom.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/m72_pkg.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/m72_pic.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/iir_filter.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/kna6034201.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/kna91h014.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/kna70h015.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/jtframe_frac_cen.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/dualport_mailbox.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/dpramv.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/board_b_d_layer.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/board_b_d.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sprite.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram_4w.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/rom.sv
|
||||
set_global_assignment -name QIP_FILE rtl/m72.qip
|
||||
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
|
||||
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
|
||||
set_global_assignment -name QIP_FILE ../../common/CPU/v30/V30.qip
|
||||
@@ -271,4 +251,5 @@ set_global_assignment -name QIP_FILE ../../common/Sound/jt51/jt51.qip
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/cpu2.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/cpu3.stp
|
||||
set_global_assignment -name AUTO_RESOURCE_SHARING ON
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<!-- mcu -->
|
||||
<part>04 00 10 00</part>
|
||||
<part name="ad_c-pr-.ic1" crc="8785e4e2"/>
|
||||
<part name="ad_c-pr-c.ic1" crc="8785e4e2"/>
|
||||
|
||||
<!-- samples -->
|
||||
<part>05 02 00 00</part>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<buttons default="B,A,R,L" names="Fire,Secondary,-,-,Start,Coin,P2 Start,Pause"></buttons>
|
||||
<switches default="04,02" base="16" page_id="1" page_name="Switches">
|
||||
<dip bits="0,1" ids="3,2,4,1" name="Lives"></dip>
|
||||
<dip bits="2" ids="Off,On" name="Demo Sounds"></dip>
|
||||
<dip bits="2" ids="On,Off" name="Demo Sounds"></dip>
|
||||
<dip bits="3" ids="80K,100K" name="Bonus Life"></dip>
|
||||
<dip bits="4,7" ids="1C/1P,2C/1P,3C/1P,4C/1P,5C/1P,6C/1P,1C/2P,1C/3P,1C/4P,1C/5P,1C/6P,2C/3P,4C/2P,5C/3P,8C/3P,Free Play" name="Coin Mode"></dip>
|
||||
<dip bits="8" ids="Off,On" name="Flip Picture"></dip>
|
||||
|
||||
20
Arcade_MiST/IremM72 Hardware/rtl/m72.qip
Normal file
20
Arcade_MiST/IremM72 Hardware/rtl/m72.qip
Normal file
@@ -0,0 +1,20 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./kna91h014.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./iir_filter.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./kna6034201.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ./jtframe_frac_cen.v ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./rom.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./pal.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sample_rom.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./board_b_d.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m72_pkg.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sound.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./kna70h015.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./ddr_debug.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./mcu.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./dualport_mailbox.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m72_pic.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sprite.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./dpramv.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./m72.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./sdram_4w.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ./board_b_d_layer.sv ]
|
||||
@@ -268,7 +268,6 @@ module line_buffer(
|
||||
output reg [7:0] pixel_out
|
||||
);
|
||||
|
||||
reg scan_buffer;
|
||||
reg [9:0] scan_pos = 0;
|
||||
wire [9:0] scan_pos_nl = scan_pos ^ {10{NL}};
|
||||
reg [7:0] line_pixel;
|
||||
@@ -281,13 +280,13 @@ dpramv #(.widthad_a(10)) buffer_0
|
||||
.clock_a(CLK_32M),
|
||||
.address_a(scan_pos_nl),
|
||||
.q_a(scan_0),
|
||||
.wren_a(!scan_buffer && CE_PIX),
|
||||
.wren_a(!V0 && CE_PIX),
|
||||
.data_a(8'd0),
|
||||
|
||||
.clock_b(CLK_96M),
|
||||
.address_b(line_position),
|
||||
.data_b(line_pixel),
|
||||
.wren_b(scan_buffer && line_write),
|
||||
.wren_b(V0 && line_write),
|
||||
.q_b()
|
||||
);
|
||||
|
||||
@@ -296,13 +295,13 @@ dpramv #(.widthad_a(10)) buffer_1
|
||||
.clock_a(CLK_32M),
|
||||
.address_a(scan_pos_nl),
|
||||
.q_a(scan_1),
|
||||
.wren_a(scan_buffer && CE_PIX),
|
||||
.wren_a(V0 && CE_PIX),
|
||||
.data_a(8'd0),
|
||||
|
||||
.clock_b(CLK_96M),
|
||||
.address_b(line_position),
|
||||
.data_b(line_pixel),
|
||||
.wren_b(!scan_buffer && line_write),
|
||||
.wren_b(!V0 && line_write),
|
||||
.q_b()
|
||||
);
|
||||
|
||||
@@ -336,9 +335,8 @@ always_ff @(posedge CLK_32M) begin
|
||||
if (old_v0 != V0) begin
|
||||
scan_pos <= 249; // TODO why?
|
||||
old_v0 <= V0;
|
||||
scan_buffer <= ~scan_buffer;
|
||||
end else if (CE_PIX) begin
|
||||
pixel_out <= scan_buffer ? scan_1 : scan_0;
|
||||
pixel_out <= V0 ? scan_1 : scan_0;
|
||||
scan_pos <= scan_pos + 10'd1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ module DRUAGA_VIDEO
|
||||
input [8:0] PV,
|
||||
output PCLK,
|
||||
output PCLK_EN,
|
||||
output [7:0] POUT, // pixel colour output
|
||||
output reg [7:0]POUT, // pixel colour output
|
||||
output VB,
|
||||
|
||||
output [10:0] VRAM_A,
|
||||
@@ -134,9 +134,9 @@ DRUAGA_SPRITE spr
|
||||
//----------------------------------------
|
||||
always @(posedge VCLKx8) if (VCLK_EN) begin
|
||||
PALT_A <= BGHI ? BGCOL : ((SPCOL[3:0]==4'd15) ? BGCOL : SPCOL );
|
||||
POUT <= PALT_D;
|
||||
end
|
||||
|
||||
assign POUT = oHB ? 8'd0 : PALT_D;
|
||||
assign PCLK = VCLK;
|
||||
assign PCLK_EN = VCLK_EN;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ assign VPOS = vcnt;
|
||||
always @(posedge MCLK) begin
|
||||
if (PCLK_EN)
|
||||
case (hcnt)
|
||||
1: begin HBLK <= 0; hcnt <= hcnt+1'd1; end
|
||||
2: begin HBLK <= 0; hcnt <= hcnt+1'd1; end
|
||||
290: begin HBLK <= 1; hcnt <= hcnt+1'd1; end
|
||||
311: begin HSYN <= 0; hcnt <= hcnt+1'd1; end
|
||||
342: begin HSYN <= 1; hcnt <= 9'd470; end
|
||||
|
||||
@@ -36,12 +36,14 @@ reg [7:0] fm [0:7];
|
||||
reg [3:0] fh [0:7];
|
||||
reg [2:0] fv [0:7];
|
||||
reg [3:0] v [0:7];
|
||||
reg [4:0] ct [0:7];
|
||||
|
||||
wire [2:0] ra = ADDR[5:3];
|
||||
|
||||
always @( posedge MCLK ) begin
|
||||
if ( CLK24M_EN & WE ) begin
|
||||
case ( ADDR[2:0] )
|
||||
3'h2: ct[ra] <= DATA[4:0];
|
||||
3'h3: v[ra] <= DATA[3:0];
|
||||
3'h4: fl[ra] <= DATA;
|
||||
3'h5: fm[ra] <= DATA;
|
||||
@@ -65,12 +67,12 @@ reg [7:0] o, ot;
|
||||
reg [19:0] c [0:7];
|
||||
reg [7:0] wa;
|
||||
reg [3:0] wm;
|
||||
reg en;
|
||||
|
||||
wire [7:0] va = WAVE_DT * wm;
|
||||
|
||||
wire [19:0] cx = c[phase];
|
||||
wire [19:0] fq = { fh[phase], fm[phase], fl[phase] };
|
||||
wire [4:0] ctx = ct[phase];
|
||||
|
||||
assign WAVE_CLK = CLK_WSGx8;
|
||||
assign WAVE_AD = wa;
|
||||
@@ -78,16 +80,15 @@ assign WAVE_AD = wa;
|
||||
always @ ( posedge MCLK ) begin
|
||||
if (CLK_WSGx8_EN) begin
|
||||
if ( phase ) begin
|
||||
ot <= ot + (en ? { 4'h0, va[7:4] } : 8'd0);
|
||||
ot <= ot + { 4'h0, va[7:4] };
|
||||
end
|
||||
else begin
|
||||
o <= ot;
|
||||
ot <= (en ? { 4'h0, va[7:4] } : 8'd0);
|
||||
ot <= { 4'h0, va[7:4] };
|
||||
end
|
||||
c[phase] <= cx + fq;
|
||||
en <= (fq!=0);
|
||||
wm <= v[phase];
|
||||
wa <= { fv[phase], cx[19:15] };
|
||||
wa <= { fv[phase], fq == 0 ? ctx[4:0] : cx[19:15] };
|
||||
phase <= phase + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
68
common/CPU/T65/README
Normal file
68
common/CPU/T65/README
Normal file
@@ -0,0 +1,68 @@
|
||||
-- 65xx compatible microprocessor core
|
||||
--
|
||||
-- Copyright (c) 2002...2015
|
||||
-- Daniel Wallner (jesus <at> opencores <dot> org)
|
||||
-- Mike Johnson (mikej <at> fpgaarcade <dot> com)
|
||||
-- Wolfgang Scherr (WoS <at> pin4 <dot> at>
|
||||
-- Morten Leikvoll ()
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author(s), but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- ----- IMPORTANT NOTES -----
|
||||
--
|
||||
-- Limitations:
|
||||
-- 65C02 and 65C816 modes are incomplete (and definitely untested after all 6502 undoc fixes)
|
||||
-- 65C02 supported : inc, dec, phx, plx, phy, ply
|
||||
-- 65D02 missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
|
||||
-- Some interface signals behave incorrect
|
||||
-- NMI interrupt handling not nice, needs further rework (to cycle-based encoding).
|
||||
--
|
||||
-- Usage:
|
||||
-- The enable signal allows clock gating / throttling without using the ready signal.
|
||||
-- Set it to constant '1' when using the Clk input as the CPU clock directly.
|
||||
--
|
||||
-- TAKE CARE you route the DO signal back to the DI signal while R_W_n='0',
|
||||
-- otherwise some undocumented opcodes won't work correctly.
|
||||
-- EXAMPLE:
|
||||
-- CPU : entity work.T65
|
||||
-- port map (
|
||||
-- R_W_n => cpu_rwn_s,
|
||||
-- [....all other ports....]
|
||||
-- DI => cpu_din_s,
|
||||
-- DO => cpu_dout_s
|
||||
-- );
|
||||
-- cpu_din_s <= cpu_dout_s when cpu_rwn_s='0' else
|
||||
-- [....other sources from peripherals and memories...]
|
||||
--
|
||||
-- ----- IMPORTANT NOTES -----
|
||||
--
|
||||
@@ -1,4 +1,4 @@
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_MCode.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_ALU.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_Pack.vhd ]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_Pack.vhd]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_ALU.vhd]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65_MCode.vhd]
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) T65.vhd]
|
||||
|
||||
@@ -194,6 +194,8 @@ architecture rtl of T65 is
|
||||
signal RstCycle : std_logic;
|
||||
signal IRQCycle : std_logic;
|
||||
signal NMICycle : std_logic;
|
||||
signal IRQReq : std_logic;
|
||||
signal NMIReq : std_logic;
|
||||
|
||||
signal SO_n_o : std_logic;
|
||||
signal IRQ_n_o : std_logic;
|
||||
@@ -354,6 +356,9 @@ begin
|
||||
MF_i <= '1';
|
||||
XF_i <= '1';
|
||||
|
||||
NMICycle <= '0';
|
||||
IRQCycle <= '0';
|
||||
|
||||
elsif Clk'event and Clk = '1' then
|
||||
if (Enable = '1') then
|
||||
-- some instructions behavior changed by the Rdy line. Detect this at the correct cycles.
|
||||
@@ -376,16 +381,24 @@ begin
|
||||
Mode_r <= Mode;
|
||||
BCD_en_r <= BCD_en;
|
||||
|
||||
if IRQCycle = '0' and NMICycle = '0' then
|
||||
if IRQReq = '0' and NMIReq = '0' then
|
||||
PC <= PC + 1;
|
||||
end if;
|
||||
|
||||
if IRQCycle = '1' or NMICycle = '1' then
|
||||
if IRQReq = '1' or NMIReq = '1' then
|
||||
IR <= "00000000";
|
||||
else
|
||||
IR <= DI;
|
||||
end if;
|
||||
|
||||
IRQCycle <= '0';
|
||||
NMICycle <= '0';
|
||||
if NMIReq = '1' then
|
||||
NMICycle <= '1';
|
||||
elsif IRQReq = '1' then
|
||||
IRQCycle <= '1';
|
||||
end if;
|
||||
|
||||
if LDS = '1' then -- LAS won't work properly if not limited to machine cycle 0
|
||||
S(7 downto 0) <= unsigned(ALU_Q);
|
||||
end if;
|
||||
@@ -499,20 +512,12 @@ begin
|
||||
|
||||
end if;
|
||||
|
||||
-- detect irq even if not rdy
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" or really_rdy = '0' then -- delay interrupts during branches (checked with Lorenz test and real 6510), not best way yet, though - but works...
|
||||
IRQ_n_o <= IRQ_n;
|
||||
end if;
|
||||
-- detect nmi even if not rdy
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510) not best way yet, though - but works...
|
||||
NMI_n_o <= NMI_n;
|
||||
end if;
|
||||
end if;
|
||||
-- act immediately on SO pin change
|
||||
-- The signal is sampled on the trailing edge of phi1 and must be externally synchronized (from datasheet)
|
||||
SO_n_o <= SO_n;
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
P(Flag_V) <= '1';
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
P(Flag_V) <= '1';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
@@ -671,29 +676,38 @@ begin
|
||||
if Res_n_i = '0' then
|
||||
MCycle <= "001";
|
||||
RstCycle <= '1';
|
||||
IRQCycle <= '0';
|
||||
NMICycle <= '0';
|
||||
NMIAct <= '0';
|
||||
IRQReq <= '0';
|
||||
NMIReq <= '0';
|
||||
elsif Clk'event and Clk = '1' then
|
||||
if (Enable = '1') then
|
||||
if (really_rdy = '1') then
|
||||
if MCycle = LCycle or Break = '1' then
|
||||
MCycle <= "000";
|
||||
RstCycle <= '0';
|
||||
IRQCycle <= '0';
|
||||
NMICycle <= '0';
|
||||
if NMIAct = '1' and IR/=x"00" then -- delay NMI further if we just executed a BRK
|
||||
NMICycle <= '1';
|
||||
NMIAct <= '0'; -- reset NMI edge detector if we start processing the NMI
|
||||
elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
|
||||
IRQCycle <= '1';
|
||||
end if;
|
||||
else
|
||||
MCycle <= std_logic_vector(unsigned(MCycle) + 1);
|
||||
end if;
|
||||
|
||||
if (IR(4 downto 0)/="10000" or Jump/="11") then -- taken branches delay the interrupts
|
||||
if NMIAct = '1' and IR/=x"00" then
|
||||
NMIReq <= '1';
|
||||
else
|
||||
NMIReq <= '0';
|
||||
end if;
|
||||
if IRQ_n_o = '0' and P(Flag_I) = '0' then
|
||||
IRQReq <= '1';
|
||||
else
|
||||
IRQReq <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
IRQ_n_o <= IRQ_n;
|
||||
NMI_n_o <= NMI_n;
|
||||
|
||||
--detect NMI even if not rdy
|
||||
if NMI_n_o = '1' and (NMI_n = '0' and (IR(4 downto 0)/="10000" or Jump/="01")) then -- branches have influence on NMI start (not best way yet, though - but works...)
|
||||
if NMI_n_o = '1' and NMI_n = '0' then
|
||||
NMIAct <= '1';
|
||||
end if;
|
||||
-- we entered NMI during BRK instruction
|
||||
|
||||
@@ -336,6 +336,8 @@ architecture arch of cpu is
|
||||
signal adjustNegate : std_logic;
|
||||
signal enterCnt : unsigned(5 downto 0);
|
||||
signal bcdOffset : unsigned(6 downto 0);
|
||||
signal bcdAccLow : unsigned(4 downto 0);
|
||||
signal bcdAccHigh : unsigned(4 downto 0);
|
||||
signal bcdAcc : unsigned(7 downto 0);
|
||||
|
||||
type tMemAccessType is
|
||||
@@ -511,6 +513,7 @@ begin
|
||||
variable result32 : unsigned(31 downto 0);
|
||||
variable result8 : unsigned(7 downto 0);
|
||||
variable result8h : unsigned(7 downto 0);
|
||||
variable result9 : unsigned(8 downto 0);
|
||||
variable newZero : std_logic;
|
||||
variable newParity : std_logic;
|
||||
variable newSign : std_logic;
|
||||
@@ -544,7 +547,8 @@ begin
|
||||
variable newRepeat : std_logic;
|
||||
variable jumpNow : std_logic;
|
||||
variable jumpAddr : unsigned(15 downto 0);
|
||||
variable bcdResult : unsigned(7 downto 0);
|
||||
variable bcdResultLow : unsigned(4 downto 0);
|
||||
variable bcdResultHigh : unsigned(4 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
|
||||
@@ -1178,7 +1182,7 @@ begin
|
||||
-- ####################################################################################
|
||||
|
||||
when CPUSTAGE_MODRM =>
|
||||
if (consumePrefetch = 0) then
|
||||
if (consumePrefetch = 0 and prefetchCount > 2) then
|
||||
regs.reg_ip <= regs.reg_ip + 1;
|
||||
consumePrefetch <= 1;
|
||||
MODRM_mem := unsigned(prefetchBuffer(2 downto 0));
|
||||
@@ -2207,24 +2211,26 @@ begin
|
||||
result := result32(15 downto 0);
|
||||
|
||||
when ALU_OP_DECADJUST =>
|
||||
result8 := regs.reg_ax(7 downto 0);
|
||||
result9 := resize(regs.reg_ax(7 downto 0), 9);
|
||||
regs.FlagCar <= '0';
|
||||
if (regs.FlagHaC = '1' or regs.reg_ax(3 downto 0) > x"9") then
|
||||
if (adjustNegate = '1') then
|
||||
result8 := result8 - 6;
|
||||
result9 := result9 - 6;
|
||||
else
|
||||
result8 := result8 + 6;
|
||||
result9 := result9 + 6;
|
||||
end if;
|
||||
regs.FlagHaC <= '1';
|
||||
regs.FlagCar <= flagCarry or result9(8);
|
||||
end if;
|
||||
if (regs.FlagCar = '1' or regs.reg_ax(7 downto 0) > x"99") then
|
||||
if (flagCarry = '1' or regs.reg_ax(7 downto 0) > x"99") then
|
||||
if (adjustNegate = '1') then
|
||||
result8 := result8 - 16#60#;
|
||||
result9 := result9 - 16#60#;
|
||||
else
|
||||
result8 := result8 + 16#60#;
|
||||
result9 := result9 + 16#60#;
|
||||
end if;
|
||||
regs.FlagCar <= '1';
|
||||
end if;
|
||||
result := x"00" & result8;
|
||||
result := x"00" & result9(7 downto 0);
|
||||
newZero := '1'; newParity := '1'; newSign := '1';
|
||||
|
||||
when ALU_OP_ASCIIADJUST =>
|
||||
@@ -2524,30 +2530,35 @@ begin
|
||||
when 5 =>
|
||||
opstep <= 6;
|
||||
if (bcdOp = BCD_OP_ADD) then
|
||||
bcdAcc <= unsigned(bus_dataread(7 downto 0)) + fetch1Val(7 downto 0);
|
||||
bcdAccLow <= resize(unsigned(bus_dataread(3 downto 0)), 5) + resize(unsigned(fetch1Val(3 downto 0)), 5);
|
||||
bcdAccHigh <= resize(unsigned(bus_dataread(7 downto 4)), 5) + resize(unsigned(fetch1Val(7 downto 4)), 5);
|
||||
else
|
||||
bcdAcc <= unsigned(bus_dataread(7 downto 0)) - fetch1Val(7 downto 0);
|
||||
bcdAccLow <= resize(unsigned(bus_dataread(3 downto 0)), 5) - resize(unsigned(fetch1Val(3 downto 0)), 5);
|
||||
bcdAccHigh <= resize(unsigned(bus_dataread(7 downto 4)), 5) - resize(unsigned(fetch1Val(7 downto 4)), 5);
|
||||
end if;
|
||||
|
||||
when 6 =>
|
||||
opstep <= 7;
|
||||
bcdResult := bcdAcc;
|
||||
if (bcdResult(3 downto 0) > x"9") then
|
||||
bcdResultLow := bcdAccLow;
|
||||
bcdResultHigh := bcdAccHigh;
|
||||
if (bcdResultLow > x"9") then
|
||||
if (bcdOp = BCD_OP_ADD) then
|
||||
bcdResult := bcdResult + 6;
|
||||
bcdResultLow := bcdResultLow + 6;
|
||||
bcdResultHigh := bcdResultHigh + 1;
|
||||
else
|
||||
bcdResult := bcdResult - 6;
|
||||
bcdResultLow := bcdResultLow - 6;
|
||||
bcdResultHigh := bcdResultHigh - 1;
|
||||
end if;
|
||||
end if;
|
||||
if (bcdResult(7 downto 0) > x"99") then
|
||||
if (bcdResultHigh > x"9") then
|
||||
if (bcdOp = BCD_OP_ADD) then
|
||||
bcdResult := bcdResult + 16#60#;
|
||||
bcdResultHigh := bcdResultHigh + 6;
|
||||
else
|
||||
bcdResult := bcdResult - 16#60#;
|
||||
bcdResultHigh := bcdResultHigh - 6;
|
||||
end if;
|
||||
regs.FlagCar <= '1';
|
||||
end if;
|
||||
bcdAcc <= bcdResult;
|
||||
bcdAcc <= bcdResultHigh(3 downto 0) & bcdResultLow(3 downto 0);
|
||||
|
||||
when 7 =>
|
||||
if (bcdOp = BCD_OP_CMP) then
|
||||
|
||||
Reference in New Issue
Block a user