Revision 438
Added by markw over 9 years ago
ultimate_cart/veronica/veronica.sdc | ||
---|---|---|
create_clock -period 40MHz [get_ports CLK]
|
||
derive_pll_clocks
|
||
derive_clock_uncertainty
|
||
|
||
create_clock -period 14MHz -name sram_clk
|
||
set_output_delay -clock sram_clk -max 60.0 [get_ports EXT_SRAM_ADDR[*]]
|
||
set_output_delay -clock sram_clk -min 0.0 [get_ports EXT_SRAM_ADDR[*]]
|
||
|
||
set_output_delay -clock sram_clk -max 60.0 [get_ports EXT_SRAM_DATA[*]]
|
||
set_output_delay -clock sram_clk -min 0.0 [get_ports EXT_SRAM_DATA[*]]
|
||
set_input_delay -clock sram_clk -max 60.0 [get_ports EXT_SRAM_DATA[*]]
|
||
set_input_delay -clock sram_clk -min 0.0 [get_ports EXT_SRAM_DATA[*]]
|
||
|
ultimate_cart/veronica/simulate_sram.sh | ||
---|---|---|
#!/bin/bash
|
||
|
||
echo "---------------------------------------------------------"
|
||
echo "Use 'simulate -run' to skip compilation stage."
|
||
echo "Use 'simulate -view' to show previous simulation results."
|
||
echo "---------------------------------------------------------"
|
||
|
||
name=sram
|
||
|
||
|
||
|
||
#. /home/markw/fpga/xilinx/14.7/ISE_DS/settings64.sh
|
||
export XILINX=C:\Xilinx\14.7\ISE_DS\ISE
|
||
|
||
mkdir -p sim
|
||
pushd sim
|
||
|
||
# if we have a WDB file, we can view it if requested (otherwise we remove it)
|
||
if [ ! -e $name.wdb -o "$1" != "-view" ]; then
|
||
|
||
rm -f $name.wdb
|
||
|
||
# if we have a EXE, we can run it if requested (otherwise we remove it)
|
||
if [ ! -e $name.exe -o "$1" != "-run" ]; then
|
||
|
||
rm -f $name.exe
|
||
|
||
# copy testbench files
|
||
cp -p ../tb_sram/* .
|
||
|
||
# copy source files
|
||
cp ../sram_mux.vhd .
|
||
# cp `find ../a8core/ -iname "*.vhd"` .
|
||
# cp `find ../a8core/ -iname "*.vhdl"` .
|
||
# cp `find ../components/ -iname "*.vhd"` .
|
||
# cp `find ../components/ -iname "*.vhdl"` .
|
||
#
|
||
# set up project definition file
|
||
ls *.vhd* | perl -e 'while (<>){s/(.*)/vhdl work $1/;print $_;}' | cat > $name.prj
|
||
echo NumericStdNoWarnings = 1 >> xilinxsim.ini
|
||
|
||
# verbose & no multthreading - fallback in case of problems
|
||
# fuse -v 1 -mt off -incremental -prj %name%.prj -o %name%.exe -t %name%
|
||
|
||
/drives/c/Xilinx/14.7/ISE_DS/ISE/bin/nt64/fuse.exe -timeprecision_vhdl 1fs -incremental -prj $name.prj -o $name.exe -t ${name}_tb || exit 1
|
||
# fuse --mt off -prj %name%.prj -o %name%.exe -t %name%_tb
|
||
|
||
# Check for the EXE again, independent of the errorlevel of fuse...
|
||
[ -e $name.exe ] || echo "No simulation executable created"
|
||
|
||
|
||
fi
|
||
|
||
# Open the iSIM GUI and run the simulation
|
||
./$name.exe -gui -f ../$name.cmd -wdb $name.wdb -log $name.log -view ../$name.wcfg || exit 1
|
||
#strace ./$name.exe -gui -f ../$name.cmd -wdb $name.wdb -log $name.log -view ../$name.wcfg >& out
|
||
#./$name.exe -h -log $name.log
|
||
|
||
|
||
else
|
||
|
||
# Only start the viewer on an existing wave configuration (from an old simulation)
|
||
isimgui -view ../$name.wcfg || exit 1
|
||
|
||
fi
|
||
|
||
popd
|
||
ultimate_cart/veronica/sram_mux.vhd | ||
---|---|---|
LIBRARY ieee;
|
||
USE ieee.std_logic_1164.all;
|
||
USE ieee.numeric_std.all;
|
||
|
||
ENTITY sram_mux IS
|
||
PORT (
|
||
clk : in std_logic;
|
||
clk7x : in std_logic;
|
||
reset_n : in std_logic;
|
||
|
||
sram_addr : out std_logic_vector(19 downto 0);
|
||
sram_data_out : out std_logic_vector(7 downto 0);
|
||
sram_drive_data : out std_logic;
|
||
sram_we_n : out std_logic;
|
||
|
||
atari_bus_request : in std_logic;
|
||
atari_sram_select : in std_logic;
|
||
atari_address : in std_logic_vector(16 downto 0);
|
||
atari_w_n : in std_logic;
|
||
atari_write_data : in std_logic_vector(7 downto 0);
|
||
|
||
veronica_address : in std_logic_vector(16 downto 0);
|
||
veronica_sram_select : in std_logic;
|
||
veronica_w_n : in std_logic;
|
||
veronica_write_data : in std_logic_vector(7 downto 0)
|
||
);
|
||
END sram_mux;
|
||
|
||
ARCHITECTURE vhdl OF sram_mux IS
|
||
signal sram_we_next : std_logic;
|
||
signal sram_we_reg : std_logic;
|
||
|
||
signal tick_next : std_logic;
|
||
signal tick_reg : std_logic;
|
||
|
||
signal tick_fast_next : std_logic_vector(6 downto 0);
|
||
signal tick_fast_reg : std_logic_vector(6 downto 0);
|
||
|
||
signal tick_mask : std_logic_vector(6 downto 0);
|
||
begin
|
||
|
||
-- Back to back writes from 65816?
|
||
process(veronica_address, veronica_write_data, veronica_w_n, veronica_sram_select,
|
||
atari_bus_request, atari_address,atari_write_data, atari_w_n, atari_sram_select)
|
||
begin
|
||
sram_addr <= (others=>'0');
|
||
sram_data_out <= (others=>'0');
|
||
sram_drive_data <= '0';
|
||
|
||
if (atari_bus_request='1') then
|
||
sram_addr(16 downto 0) <= atari_address;
|
||
sram_data_out <= atari_write_data;
|
||
sram_we_next <= (atari_w_n or not(atari_sram_select));
|
||
sram_drive_data <= not(atari_w_n);
|
||
else
|
||
sram_addr(16 downto 0) <= veronica_address;
|
||
sram_data_out <= veronica_write_data;
|
||
sram_we_next <= (veronica_w_n or not(veronica_sram_select));
|
||
sram_drive_data <= not(veronica_w_n);
|
||
end if;
|
||
end process;
|
||
|
||
--
|
||
-- 12345
|
||
-- 01111
|
||
-- 00000
|
||
process(clk,reset_n)
|
||
begin
|
||
if (reset_n='0') then
|
||
tick_reg <= '0';
|
||
elsif (clk'event and clk='1') then
|
||
tick_reg <= tick_next;
|
||
end if;
|
||
end process;
|
||
tick_next <= not(tick_reg);
|
||
|
||
process(clk7x,reset_n)
|
||
begin
|
||
if (reset_n='0') then
|
||
tick_fast_reg <= (others=>'0');
|
||
sram_we_reg <= '1';
|
||
elsif (clk7x'event and clk7x='1') then
|
||
tick_fast_reg <= tick_fast_next;
|
||
sram_we_reg <= sram_we_next;
|
||
end if;
|
||
end process;
|
||
tick_fast_next <= tick_fast_reg(5 downto 0)&tick_reg;
|
||
|
||
tick_mask <= (tick_reg&tick_reg&tick_reg&tick_reg&tick_reg&tick_reg&tick_reg) xor tick_fast_reg; --1000000 1000000 1000000 (raise WE - how long must WE be high?)
|
||
|
||
-- 55 addr, 45 write pulse, 20 we -> drive
|
||
-- 71.4 total -> 7x clock-> about 10ns
|
||
-- 10 (we high), 60 (we low) 1 000 000
|
||
-- 30 (no drive), 40 (drive) 0 001 111
|
||
|
||
sram_we_n <= sram_we_reg;
|
||
|
||
end vhdl;
|
||
ultimate_cart/veronica/tb_sram/sram_tb.vhd | ||
---|---|---|
library ieee;
|
||
use ieee.std_logic_1164.all;
|
||
use ieee.std_logic_unsigned.all;
|
||
use ieee.numeric_std.all;
|
||
use ieee.std_logic_textio.all;
|
||
|
||
library std_developerskit ; -- used for to_string
|
||
-- use std_developerskit.std_iopak.all;
|
||
|
||
entity sram_tb is
|
||
end;
|
||
|
||
architecture rtl of sram_tb is
|
||
|
||
constant CLK_PERIOD : time := 1 us / (14);
|
||
constant CLK_FAST_PERIOD : time := 1 us / (14*7);
|
||
|
||
signal reset_n : std_logic;
|
||
signal clk : std_logic;
|
||
signal clk_fast : std_logic;
|
||
|
||
signal EXT_SRAM_ADDR: std_logic_vector(19 downto 0);
|
||
signal EXT_SRAM_DATA: std_logic_vector(7 downto 0);
|
||
signal EXT_SRAM_CE: std_logic;
|
||
signal EXT_SRAM_OE: std_logic;
|
||
signal EXT_SRAM_WE: std_logic;
|
||
|
||
-- 65816 bus
|
||
signal veronica_address : std_logic_vector(23 downto 0);
|
||
signal veronica_read_data : std_logic_vector(7 downto 0);
|
||
signal veronica_write_data : std_logic_vector(7 downto 0);
|
||
signal veronica_w_n : std_logic;
|
||
signal veronica_config_w_n : std_logic;
|
||
|
||
-- 6502 bus
|
||
signal atari_bus_request : std_logic;
|
||
signal atari_address : std_logic_vector(12 downto 0);
|
||
signal atari_data_bus : std_logic_vector(7 downto 0);
|
||
signal atari_read_data : std_logic_vector(7 downto 0);
|
||
signal atari_write_data : std_logic_vector(7 downto 0);
|
||
signal atari_w_n : std_logic;
|
||
signal atari_config_w_n : std_logic;
|
||
signal atari_s4 : std_logic;
|
||
signal atari_s5 : std_logic;
|
||
signal atari_ctl : std_logic;
|
||
|
||
-- address decode
|
||
signal veronica_config_select : std_logic;
|
||
signal veronica_sram_select : std_logic;
|
||
signal veronica_sram_address: std_logic_vector(16 downto 0);
|
||
signal atari_config_select : std_logic;
|
||
signal atari_sram_select : std_logic;
|
||
signal atari_sram_address: std_logic_vector(16 downto 0);
|
||
|
||
-- veronica config
|
||
signal veronica_window_address : std_logic;
|
||
signal veronica_bank_half_select : std_logic;
|
||
signal veronica_config_data : std_logic_vector(7 downto 0);
|
||
|
||
-- atari config
|
||
signal atari_banka_enable : std_logic;
|
||
signal atari_bank8_enable : std_logic;
|
||
signal atari_bank_half_select : std_logic;
|
||
signal atari_config_data : std_logic_vector(7 downto 0);
|
||
|
||
-- common config
|
||
signal common_sem : std_logic;
|
||
signal common_bank_select : std_logic;
|
||
|
||
-- cart driving
|
||
signal cart_bus_data_out : std_logic_vector(7 downto 0);
|
||
signal cart_bus_drive : std_logic;
|
||
|
||
-- sram driving
|
||
signal sram_write_data : std_logic_vector(7 downto 0);
|
||
signal sram_drive_data : std_logic;
|
||
signal sram_read_data : std_logic_vector(7 downto 0);
|
||
|
||
begin
|
||
p_clk_gen_a : process
|
||
begin
|
||
clk <= '1';
|
||
wait for CLK_PERIOD/2;
|
||
clk <= '0';
|
||
wait for CLK_PERIOD - (CLK_PERIOD/2 );
|
||
end process;
|
||
|
||
p_clk_gen_b : process
|
||
begin
|
||
clk_fast <= '1';
|
||
wait for CLK_FAST_PERIOD/2;
|
||
clk_fast <= '0';
|
||
wait for CLK_FAST_PERIOD - (CLK_FAST_PERIOD/2 );
|
||
end process;
|
||
|
||
reset_n <= '0', '1' after 1000ns;
|
||
|
||
process_setup_sram : process
|
||
begin
|
||
atari_bus_request <= '0';
|
||
atari_sram_select <= '0';
|
||
atari_address <= (others=>'0');
|
||
atari_w_n <= '1';
|
||
atari_write_data <= (others=>'0');
|
||
|
||
veronica_address <= (others=>'0');
|
||
veronica_sram_select <= '0';
|
||
veronica_w_n <= '1';
|
||
veronica_write_data <= (others=>'0');
|
||
|
||
wait for 1100ns;
|
||
|
||
wait until clk'event and clk = '1';
|
||
atari_w_n <= '0';
|
||
atari_address<= '0'&x"402";
|
||
atari_write_data <= x"56";
|
||
|
||
wait until clk'event and clk = '1';
|
||
atari_w_n <= '0';
|
||
atari_address<= '0'&x"313";
|
||
atari_write_data <= x"65";
|
||
|
||
wait until clk'event and clk = '1';
|
||
atari_w_n <= '0';
|
||
atari_address<= '0'&x"402";
|
||
atari_write_data <= x"56";
|
||
|
||
wait for 100000000us;
|
||
|
||
end process;
|
||
|
||
glue6: entity work.sram_mux
|
||
port map
|
||
(
|
||
clk => clk,
|
||
clk7x => clk_fast,
|
||
reset_n => reset_n,
|
||
|
||
sram_addr => EXT_SRAM_ADDR,
|
||
sram_data_out => sram_write_data,
|
||
sram_drive_data => sram_drive_data,
|
||
sram_we_n => EXT_SRAM_WE,
|
||
|
||
atari_bus_request => atari_bus_request,
|
||
atari_sram_select => atari_sram_select,
|
||
atari_address => atari_sram_address,
|
||
atari_w_n => atari_w_n,
|
||
atari_write_data => atari_write_data,
|
||
|
||
veronica_address => veronica_sram_address,
|
||
veronica_sram_select => veronica_sram_select,
|
||
veronica_w_n => veronica_w_n,
|
||
veronica_write_data => veronica_write_data
|
||
);
|
||
|
||
end rtl;
|
||
|
ultimate_cart/veronica/BCDMath.v | ||
---|---|---|
`timescale 1ns / 1ps
|
||
//=============================================================================
|
||
// __
|
||
// \\__/ o\ (C) 2012 Robert Finch
|
||
// \ __ / All rights reserved.
|
||
// \/_// robfinch<remove>@opencores.org
|
||
// ||
|
||
//
|
||
// BCDMath.v
|
||
//
|
||
//
|
||
// This source file is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU Lesser General Public License as published
|
||
// by the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// This source file is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
//
|
||
//
|
||
//=============================================================================
|
||
//
|
||
module BCDAdd(ci,a,b,o,c);
|
||
input ci; // carry input
|
||
input [7:0] a;
|
||
input [7:0] b;
|
||
output [7:0] o;
|
||
output c;
|
||
|
||
wire c0,c1;
|
||
|
||
wire [4:0] hsN0 = a[3:0] + b[3:0] + ci;
|
||
wire [4:0] hsN1 = a[7:4] + b[7:4] + c0;
|
||
|
||
BCDAddAdjust u1 (hsN0,o[3:0],c0);
|
||
BCDAddAdjust u2 (hsN1,o[7:4],c);
|
||
|
||
endmodule
|
||
|
||
module BCDAdd4(ci,a,b,o,c,c8);
|
||
input ci; // carry input
|
||
input [15:0] a;
|
||
input [15:0] b;
|
||
output [15:0] o;
|
||
output c;
|
||
output c8;
|
||
|
||
wire c0,c1,c2;
|
||
assign c8 = c1;
|
||
|
||
wire [4:0] hsN0 = a[3:0] + b[3:0] + ci;
|
||
wire [4:0] hsN1 = a[7:4] + b[7:4] + c0;
|
||
wire [4:0] hsN2 = a[11:8] + b[11:8] + c1;
|
||
wire [4:0] hsN3 = a[15:12] + b[15:12] + c2;
|
||
|
||
BCDAddAdjust u1 (hsN0,o[3:0],c0);
|
||
BCDAddAdjust u2 (hsN1,o[7:4],c1);
|
||
BCDAddAdjust u3 (hsN2,o[11:8],c2);
|
||
BCDAddAdjust u4 (hsN3,o[15:12],c);
|
||
|
||
endmodule
|
||
|
||
module BCDSub(ci,a,b,o,c);
|
||
input ci; // carry input
|
||
input [7:0] a;
|
||
input [7:0] b;
|
||
output [7:0] o;
|
||
output c;
|
||
|
||
wire c0,c1;
|
||
|
||
wire [4:0] hdN0 = a[3:0] - b[3:0] - ci;
|
||
wire [4:0] hdN1 = a[7:4] - b[7:4] - c0;
|
||
|
||
BCDSubAdjust u1 (hdN0,o[3:0],c0);
|
||
BCDSubAdjust u2 (hdN1,o[7:4],c);
|
||
|
||
endmodule
|
||
|
||
module BCDSub4(ci,a,b,o,c,c8);
|
||
input ci; // carry input
|
||
input [15:0] a;
|
||
input [15:0] b;
|
||
output [15:0] o;
|
||
output c;
|
||
output c8;
|
||
|
||
wire c0,c1,c2;
|
||
assign c8 = c1;
|
||
|
||
wire [4:0] hdN0 = a[3:0] - b[3:0] - ci;
|
||
wire [4:0] hdN1 = a[7:4] - b[7:4] - c0;
|
||
wire [4:0] hdN2 = a[11:8] - b[11:8] - c1;
|
||
wire [4:0] hdN3 = a[15:12] - b[15:12] - c2;
|
||
|
||
BCDSubAdjust u1 (hdN0,o[3:0],c0);
|
||
BCDSubAdjust u2 (hdN1,o[7:4],c1);
|
||
BCDSubAdjust u3 (hdN2,o[11:8],c2);
|
||
BCDSubAdjust u4 (hdN3,o[15:12],c);
|
||
|
||
endmodule
|
||
|
||
module BCDAddAdjust(i,o,c);
|
||
input [4:0] i;
|
||
output [3:0] o;
|
||
reg [3:0] o;
|
||
output c;
|
||
reg c;
|
||
always @(i)
|
||
case(i)
|
||
5'h0: begin o = 4'h0; c = 1'b0; end
|
||
5'h1: begin o = 4'h1; c = 1'b0; end
|
||
5'h2: begin o = 4'h2; c = 1'b0; end
|
||
5'h3: begin o = 4'h3; c = 1'b0; end
|
||
5'h4: begin o = 4'h4; c = 1'b0; end
|
||
5'h5: begin o = 4'h5; c = 1'b0; end
|
||
5'h6: begin o = 4'h6; c = 1'b0; end
|
||
5'h7: begin o = 4'h7; c = 1'b0; end
|
||
5'h8: begin o = 4'h8; c = 1'b0; end
|
||
5'h9: begin o = 4'h9; c = 1'b0; end
|
||
5'hA: begin o = 4'h0; c = 1'b1; end
|
||
5'hB: begin o = 4'h1; c = 1'b1; end
|
||
5'hC: begin o = 4'h2; c = 1'b1; end
|
||
5'hD: begin o = 4'h3; c = 1'b1; end
|
||
5'hE: begin o = 4'h4; c = 1'b1; end
|
||
5'hF: begin o = 4'h5; c = 1'b1; end
|
||
5'h10: begin o = 4'h6; c = 1'b1; end
|
||
5'h11: begin o = 4'h7; c = 1'b1; end
|
||
5'h12: begin o = 4'h8; c = 1'b1; end
|
||
5'h13: begin o = 4'h9; c = 1'b1; end
|
||
default: begin o = 4'h9; c = 1'b1; end
|
||
endcase
|
||
endmodule
|
||
|
||
module BCDSubAdjust(i,o,c);
|
||
input [4:0] i;
|
||
output [3:0] o;
|
||
reg [3:0] o;
|
||
output c;
|
||
reg c;
|
||
always @(i)
|
||
case(i)
|
||
5'h0: begin o = 4'h0; c = 1'b0; end
|
||
5'h1: begin o = 4'h1; c = 1'b0; end
|
||
5'h2: begin o = 4'h2; c = 1'b0; end
|
||
5'h3: begin o = 4'h3; c = 1'b0; end
|
||
5'h4: begin o = 4'h4; c = 1'b0; end
|
||
5'h5: begin o = 4'h5; c = 1'b0; end
|
||
5'h6: begin o = 4'h6; c = 1'b0; end
|
||
5'h7: begin o = 4'h7; c = 1'b0; end
|
||
5'h8: begin o = 4'h8; c = 1'b0; end
|
||
5'h9: begin o = 4'h9; c = 1'b0; end
|
||
5'h16: begin o = 4'h0; c = 1'b1; end
|
||
5'h17: begin o = 4'h1; c = 1'b1; end
|
||
5'h18: begin o = 4'h2; c = 1'b1; end
|
||
5'h19: begin o = 4'h3; c = 1'b1; end
|
||
5'h1A: begin o = 4'h4; c = 1'b1; end
|
||
5'h1B: begin o = 4'h5; c = 1'b1; end
|
||
5'h1C: begin o = 4'h6; c = 1'b1; end
|
||
5'h1D: begin o = 4'h7; c = 1'b1; end
|
||
5'h1E: begin o = 4'h8; c = 1'b1; end
|
||
5'h1F: begin o = 4'h9; c = 1'b1; end
|
||
default: begin o = 4'h9; c = 1'b1; end
|
||
endcase
|
||
endmodule
|
||
|
||
// Multiply two BCD digits
|
||
// Method used is table lookup
|
||
module BCDMul1(a,b,o);
|
||
input [3:0] a;
|
||
input [3:0] b;
|
||
output [7:0] o;
|
||
reg [7:0] o;
|
||
|
||
always @(a or b)
|
||
casex({a,b})
|
||
8'h00: o = 8'h00;
|
||
8'h01: o = 8'h00;
|
||
8'h02: o = 8'h00;
|
||
8'h03: o = 8'h00;
|
||
8'h04: o = 8'h00;
|
||
8'h05: o = 8'h00;
|
||
8'h06: o = 8'h00;
|
||
8'h07: o = 8'h00;
|
||
8'h08: o = 8'h00;
|
||
8'h09: o = 8'h00;
|
||
8'h10: o = 8'h00;
|
||
8'h11: o = 8'h01;
|
||
8'h12: o = 8'h02;
|
||
8'h13: o = 8'h03;
|
||
8'h14: o = 8'h04;
|
||
8'h15: o = 8'h05;
|
||
8'h16: o = 8'h06;
|
||
8'h17: o = 8'h07;
|
||
8'h18: o = 8'h08;
|
||
8'h19: o = 8'h09;
|
||
8'h20: o = 8'h00;
|
||
8'h21: o = 8'h02;
|
||
8'h22: o = 8'h04;
|
||
8'h23: o = 8'h06;
|
||
8'h24: o = 8'h08;
|
||
8'h25: o = 8'h10;
|
||
8'h26: o = 8'h12;
|
||
8'h27: o = 8'h14;
|
||
8'h28: o = 8'h16;
|
||
8'h29: o = 8'h18;
|
||
8'h30: o = 8'h00;
|
||
8'h31: o = 8'h03;
|
||
8'h32: o = 8'h06;
|
||
8'h33: o = 8'h09;
|
||
8'h34: o = 8'h12;
|
||
8'h35: o = 8'h15;
|
||
8'h36: o = 8'h18;
|
||
8'h37: o = 8'h21;
|
||
8'h38: o = 8'h24;
|
||
8'h39: o = 8'h27;
|
||
8'h40: o = 8'h00;
|
||
8'h41: o = 8'h04;
|
||
8'h42: o = 8'h08;
|
||
8'h43: o = 8'h12;
|
||
8'h44: o = 8'h16;
|
||
8'h45: o = 8'h20;
|
||
8'h46: o = 8'h24;
|
||
8'h47: o = 8'h28;
|
||
8'h48: o = 8'h32;
|
||
8'h49: o = 8'h36;
|
||
8'h50: o = 8'h00;
|
||
8'h51: o = 8'h05;
|
||
8'h52: o = 8'h10;
|
||
8'h53: o = 8'h15;
|
||
8'h54: o = 8'h20;
|
||
8'h55: o = 8'h25;
|
||
8'h56: o = 8'h30;
|
||
8'h57: o = 8'h35;
|
||
8'h58: o = 8'h40;
|
||
8'h59: o = 8'h45;
|
||
8'h60: o = 8'h00;
|
||
8'h61: o = 8'h06;
|
||
8'h62: o = 8'h12;
|
||
8'h63: o = 8'h18;
|
||
8'h64: o = 8'h24;
|
||
8'h65: o = 8'h30;
|
||
8'h66: o = 8'h36;
|
||
8'h67: o = 8'h42;
|
||
8'h68: o = 8'h48;
|
||
8'h69: o = 8'h54;
|
||
8'h70: o = 8'h00;
|
||
8'h71: o = 8'h07;
|
||
8'h72: o = 8'h14;
|
||
8'h73: o = 8'h21;
|
||
8'h74: o = 8'h28;
|
||
8'h75: o = 8'h35;
|
||
8'h76: o = 8'h42;
|
||
8'h77: o = 8'h49;
|
||
8'h78: o = 8'h56;
|
||
8'h79: o = 8'h63;
|
||
8'h80: o = 8'h00;
|
||
8'h81: o = 8'h08;
|
||
8'h82: o = 8'h16;
|
||
8'h83: o = 8'h24;
|
||
8'h84: o = 8'h32;
|
||
8'h85: o = 8'h40;
|
||
8'h86: o = 8'h48;
|
||
8'h87: o = 8'h56;
|
||
8'h88: o = 8'h64;
|
||
8'h89: o = 8'h72;
|
||
8'h90: o = 8'h00;
|
||
8'h91: o = 8'h09;
|
||
8'h92: o = 8'h18;
|
||
8'h93: o = 8'h27;
|
||
8'h94: o = 8'h36;
|
||
8'h95: o = 8'h45;
|
||
8'h96: o = 8'h54;
|
||
8'h97: o = 8'h63;
|
||
8'h98: o = 8'h72;
|
||
8'h99: o = 8'h81;
|
||
default: o = 8'h00;
|
||
endcase
|
||
endmodule
|
||
|
||
|
||
// Multiply two pairs of BCD digits
|
||
// handles from 0x0 to 99x99
|
||
module BCDMul2(a,b,o);
|
||
input [7:0] a;
|
||
input [7:0] b;
|
||
output [15:0] o;
|
||
|
||
wire [7:0] p1,p2,p3,p4;
|
||
wire [15:0] s1;
|
||
|
||
BCDMul1 u1 (a[3:0],b[3:0],p1);
|
||
BCDMul1 u2 (a[7:4],b[3:0],p2);
|
||
BCDMul1 u3 (a[3:0],b[7:4],p3);
|
||
BCDMul1 u4 (a[7:4],b[7:4],p4);
|
||
|
||
BCDAdd4 u5 (1'b0,{p4,p1},{4'h0,p2,4'h0},s1);
|
||
BCDAdd4 u6 (1'b0,s1,{4'h0,p3,4'h0},o);
|
||
|
||
endmodule
|
||
|
||
module BCDMul_tb();
|
||
|
||
wire [15:0] o1,o2,o3,o4;
|
||
|
||
BCDMul2 u1 (8'h00,8'h00,o1);
|
||
BCDMul2 u2 (8'h99,8'h99,o2);
|
||
BCDMul2 u3 (8'h25,8'h18,o3);
|
||
BCDMul2 u4 (8'h37,8'h21,o4);
|
||
|
||
endmodule
|
ultimate_cart/veronica/FT816.v | ||
---|---|---|
`timescale 1ns / 1ps
|
||
// ============================================================================
|
||
// __
|
||
// \\__/ o\ (C) 2013, 2014 Robert Finch, Stratford
|
||
// \ __ / All rights reserved.
|
||
// \/_// robfinch<remove>@finitron.ca
|
||
// ||
|
||
//
|
||
// FT816.v
|
||
// - 16 bit CPU
|
||
//
|
||
// This source file is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU Lesser General Public License as published
|
||
// by the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// This source file is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
//
|
||
// ============================================================================
|
||
//
|
||
`define TRUE 1'b1
|
||
`define FALSE 1'b0
|
||
|
||
`define DEBUG 1'b1
|
||
|
||
`define SUPPORT_ICACHE 1'b1
|
||
`define ICACHE_4K 1'b1
|
||
//`define ICACHE_16K 1'b1
|
||
//`define ICACHE_2WAY 1'b1
|
||
//`define SUPPORT_DCACHE 1'b1
|
||
`define SUPPORT_BCD 1'b1
|
||
`define SUPPORT_DIVMOD 1'b1
|
||
`define SUPPORT_EM8 1'b1
|
||
`define SUPPORT_816 1'b1
|
||
//`define SUPPORT_EXEC 1'b1
|
||
`define SUPPORT_BERR 1'b1
|
||
`define SUPPORT_STRING 1'b1
|
||
`define SUPPORT_SHIFT 1'b1
|
||
//`define SUPPORT_CGI 1'b1 // support the control giveaway interrupt
|
||
|
||
`define BRK_VECTNO 9'd0
|
||
`define SLP_VECTNO 9'd1
|
||
`define BYTE_RST_VECT 24'h00FFFC
|
||
`define BYTE_NMI_VECT 24'h00FFFA
|
||
`define BYTE_IRQ_VECT 24'h00FFFE
|
||
`define BYTE_ABT_VECT 24'h00FFF8
|
||
`define BYTE_COP_VECT 24'h00FFF4
|
||
`define RST_VECT_816 24'h00FFFC
|
||
`define IRQ_VECT_816 24'h00FFEE
|
||
`define NMI_VECT_816 24'h00FFEA
|
||
`define ABT_VECT_816 24'h00FFE8
|
||
`define BRK_VECT_816 24'h00FFE6
|
||
`define COP_VECT_816 24'h00FFE4
|
||
|
||
`define BRK 9'h00
|
||
`define RTI 9'h40
|
||
`define RTS 9'h60
|
||
`define PHP 9'h08
|
||
`define CLC 9'h18
|
||
`define PLP 9'h28
|
||
`define SEC 9'h38
|
||
`define PHA 9'h48
|
||
`define CLI 9'h58
|
||
`define PLA 9'h68
|
||
`define SEI 9'h78
|
||
`define DEY 9'h88
|
||
`define TYA 9'h98
|
||
`define TAY 9'hA8
|
||
`define CLV 9'hB8
|
||
`define INY 9'hC8
|
||
`define CLD 9'hD8
|
||
`define INX 9'hE8
|
||
`define SED 9'hF8
|
||
`define ROR_ACC 9'h6A
|
||
`define TXA 9'h8A
|
||
`define TXS 9'h9A
|
||
`define TAX 9'hAA
|
||
`define TSX 9'hBA
|
||
`define DEX 9'hCA
|
||
`define NOP 9'hEA
|
||
`define TXY 9'h9B
|
||
`define TYX 9'hBB
|
||
`define TAS 9'h1B
|
||
`define TSA 9'h3B
|
||
`define TRS 9'h8B
|
||
`define TSR 9'hAB
|
||
`define TCD 9'h5B
|
||
`define TDC 9'h7B
|
||
`define STP 9'hDB
|
||
`define NAT 9'hFB
|
||
`define EMM 9'hFB
|
||
`define XCE 9'hFB
|
||
`define INA 9'h1A
|
||
`define DEA 9'h3A
|
||
`define SEP 9'hE2
|
||
`define REP 9'hC2
|
||
`define PEA 9'hF4
|
||
`define PEI 9'hD4
|
||
`define PER 9'h62
|
||
`define WDM 9'h42
|
||
|
||
// CMP = SUB r0,....
|
||
|
||
`define ADC_IMM 9'h69
|
||
`define ADC_ZP 9'h65
|
||
`define ADC_ZPX 9'h75
|
||
`define ADC_IX 9'h61
|
||
`define ADC_IY 9'h71
|
||
`define ADC_IYL 9'h77
|
||
`define ADC_ABS 9'h6D
|
||
`define ADC_ABSX 9'h7D
|
||
`define ADC_ABSY 9'h79
|
||
`define ADC_I 9'h72
|
||
`define ADC_IL 9'h67
|
||
`define ADC_AL 9'h6F
|
||
`define ADC_ALX 9'h7F
|
||
`define ADC_DSP 9'h63
|
||
`define ADC_DSPIY 9'h73
|
||
|
||
`define SBC_IMM 9'hE9
|
||
`define SBC_ZP 9'hE5
|
||
`define SBC_ZPX 9'hF5
|
||
`define SBC_IX 9'hE1
|
||
`define SBC_IY 9'hF1
|
||
`define SBC_IYL 9'hF7
|
||
`define SBC_ABS 9'hED
|
||
`define SBC_ABSX 9'hFD
|
||
`define SBC_ABSY 9'hF9
|
||
`define SBC_I 9'hF2
|
||
`define SBC_IL 9'hE7
|
||
`define SBC_AL 9'hEF
|
||
`define SBC_ALX 9'hFF
|
||
`define SBC_DSP 9'hE3
|
||
`define SBC_DSPIY 9'hF3
|
||
|
||
`define CMP_IMM 9'hC9
|
||
`define CMP_ZP 9'hC5
|
||
`define CMP_ZPX 9'hD5
|
||
`define CMP_IX 9'hC1
|
||
`define CMP_IY 9'hD1
|
||
`define CMP_IYL 8'hD7
|
||
`define CMP_ABS 9'hCD
|
||
`define CMP_ABSX 9'hDD
|
||
`define CMP_ABSY 9'hD9
|
||
`define CMP_I 9'hD2
|
||
`define CMP_IL 9'hC7
|
||
`define CMP_AL 9'hCF
|
||
`define CMP_ALX 9'hDF
|
||
`define CMP_DSP 9'hC3
|
||
`define CMP_DSPIY 9'hD3
|
||
|
||
`define LDA_IMM8 9'hA5
|
||
`define LDA_IMM16 9'hB9
|
||
`define LDA_IMM32 9'hA9
|
||
|
||
`define AND_IMM 9'h29
|
||
`define AND_ZP 9'h25
|
||
`define AND_ZPX 9'h35
|
||
`define AND_IX 9'h21
|
||
`define AND_IY 9'h31
|
||
`define AND_IYL 9'h37
|
||
`define AND_ABS 9'h2D
|
||
`define AND_ABSX 9'h3D
|
||
`define AND_ABSY 9'h39
|
||
`define AND_RIND 9'h32
|
||
`define AND_I 9'h32
|
||
`define AND_IL 9'h27
|
||
`define AND_DSP 9'h23
|
||
`define AND_DSPIY 9'h33
|
||
`define AND_AL 9'h2F
|
||
`define AND_ALX 9'h3F
|
||
|
||
`define ORA_IMM 9'h09
|
||
`define ORA_ZP 9'h05
|
||
`define ORA_ZPX 9'h15
|
||
`define ORA_IX 9'h01
|
||
`define ORA_IY 9'h11
|
||
`define ORA_IYL 9'h17
|
||
`define ORA_ABS 9'h0D
|
||
`define ORA_ABSX 9'h1D
|
||
`define ORA_ABSY 9'h19
|
||
`define ORA_I 9'h12
|
||
`define ORA_IL 9'h07
|
||
`define ORA_AL 9'h0F
|
||
`define ORA_ALX 9'h1F
|
||
`define ORA_DSP 9'h03
|
||
`define ORA_DSPIY 9'h13
|
||
|
||
`define EOR_IMM 9'h49
|
||
`define EOR_ZP 9'h45
|
||
`define EOR_ZPX 9'h55
|
||
`define EOR_IX 9'h41
|
||
`define EOR_IY 9'h51
|
||
`define EOR_IYL 9'h57
|
||
`define EOR_ABS 9'h4D
|
||
`define EOR_ABSX 9'h5D
|
||
`define EOR_ABSY 9'h59
|
||
`define EOR_RIND 9'h52
|
||
`define EOR_I 9'h52
|
||
`define EOR_IL 9'h47
|
||
`define EOR_DSP 9'h43
|
||
`define EOR_DSPIY 9'h53
|
||
`define EOR_AL 9'h4F
|
||
`define EOR_ALX 9'h5F
|
||
|
||
//`define LDB_RIND 9'hB2 // Conflict with LDX #imm16
|
||
|
||
`define LDA_IMM 9'hA9
|
||
`define LDA_ZP 9'hA5
|
||
`define LDA_ZPX 9'hB5
|
||
`define LDA_IX 9'hA1
|
||
`define LDA_IY 9'hB1
|
||
`define LDA_IYL 9'hB7
|
||
`define LDA_ABS 9'hAD
|
||
`define LDA_ABSX 9'hBD
|
||
`define LDA_ABSY 9'hB9
|
||
`define LDA_I 9'hB2
|
||
`define LDA_IL 9'hA7
|
||
`define LDA_AL 9'hAF
|
||
`define LDA_ALX 9'hBF
|
||
`define LDA_DSP 9'hA3
|
||
`define LDA_DSPIY 9'hB3
|
||
|
||
`define STA_ZP 9'h85
|
||
`define STA_ZPX 9'h95
|
||
`define STA_IX 9'h81
|
||
`define STA_IY 9'h91
|
||
`define STA_IYL 9'h97
|
||
`define STA_ABS 9'h8D
|
||
`define STA_ABSX 9'h9D
|
||
`define STA_ABSY 9'h99
|
||
`define STA_I 9'h92
|
||
`define STA_IL 9'h87
|
||
`define STA_AL 9'h8F
|
||
`define STA_ALX 9'h9F
|
||
`define STA_DSP 9'h83
|
||
`define STA_DSPIY 9'h93
|
||
|
||
`define ASL_ACC 9'h0A
|
||
`define ASL_ZP 9'h06
|
||
`define ASL_RR 9'h06
|
||
`define ASL_ZPX 9'h16
|
||
`define ASL_ABS 9'h0E
|
||
`define ASL_ABSX 9'h1E
|
||
|
||
`define ROL_ACC 9'h2A
|
||
`define ROL_ZP 9'h26
|
||
`define ROL_RR 9'h26
|
||
`define ROL_ZPX 9'h36
|
||
`define ROL_ABS 9'h2E
|
||
`define ROL_ABSX 9'h3E
|
||
|
||
`define LSR_ACC 9'h4A
|
||
`define LSR_ZP 9'h46
|
||
`define LSR_RR 9'h46
|
||
`define LSR_ZPX 9'h56
|
||
`define LSR_ABS 9'h4E
|
||
`define LSR_ABSX 9'h5E
|
||
|
||
`define ROR_RR 9'h66
|
||
`define ROR_ZP 9'h66
|
||
`define ROR_ZPX 9'h76
|
||
`define ROR_ABS 9'h6E
|
||
`define ROR_ABSX 9'h7E
|
||
|
||
`define DEC_RR 9'hC6
|
||
`define DEC_ZP 9'hC6
|
||
`define DEC_ZPX 9'hD6
|
||
`define DEC_ABS 9'hCE
|
||
`define DEC_ABSX 9'hDE
|
||
`define INC_RR 9'hE6
|
||
`define INC_ZP 9'hE6
|
||
`define INC_ZPX 9'hF6
|
||
`define INC_ABS 9'hEE
|
||
`define INC_ABSX 9'hFE
|
||
|
||
`define BIT_IMM 9'h89
|
||
`define BIT_ZP 9'h24
|
||
`define BIT_ZPX 9'h34
|
||
`define BIT_ABS 9'h2C
|
||
`define BIT_ABSX 9'h3C
|
||
|
||
// CMP = SUB r0,...
|
||
// BIT = AND r0,...
|
||
`define BPL 9'h10
|
||
`define BVC 9'h50
|
||
`define BCC 9'h90
|
||
`define BNE 9'hD0
|
||
`define BMI 9'h30
|
||
`define BVS 9'h70
|
||
`define BCS 9'hB0
|
||
`define BEQ 9'hF0
|
||
`define BRL 9'h82
|
||
`define BRA 9'h80
|
||
|
||
`define JML 9'h5C
|
||
`define JMP 9'h4C
|
||
`define JMP_IND 9'h6C
|
||
`define JMP_INDX 9'h7C
|
||
`define JMP_RIND 9'hD2
|
||
`define JSR 9'h20
|
||
`define JSL 9'h22
|
||
`define JSR_IND 9'h2C
|
||
`define JSR_INDX 9'hFC
|
||
`define JSR_RIND 9'hC2
|
||
`define RTS 9'h60
|
||
`define RTL 9'h6B
|
||
`define BSR 9'h62
|
||
`define NOP 9'hEA
|
||
|
||
`define BRK 9'h00
|
||
`define PLX 9'hFA
|
||
`define PLY 9'h7A
|
||
`define PHX 9'hDA
|
||
`define PHY 9'h5A
|
||
`define WAI 9'hCB
|
||
`define PUSH 9'h0B
|
||
`define POP 9'h2B
|
||
`define PHB 9'h8B
|
||
`define PHD 9'h0B
|
||
`define PHK 9'h4B
|
||
`define XBA 9'hEB
|
||
`define COP 9'h02
|
||
`define PLB 9'hAB
|
||
`define PLD 9'h2B
|
||
`define PSHR4 9'h0F
|
||
`define POPR4 9'h2F
|
||
|
||
`define LDX_IMM 9'hA2
|
||
`define LDX_ZP 9'hA6
|
||
`define LDX_ZPX 9'hB6
|
||
`define LDX_ZPY 9'hB6
|
||
`define LDX_ABS 9'hAE
|
||
`define LDX_ABSY 9'hBE
|
||
|
||
`define LDX_IMM32 9'hA2
|
||
`define LDX_IMM16 9'hB2
|
||
`define LDX_IMM8 9'hA6
|
||
|
||
`define LDY_IMM 9'hA0
|
||
`define LDY_ZP 9'hA4
|
||
`define LDY_ZPX 9'hB4
|
||
`define LDY_IMM32 9'hA0
|
||
`define LDY_IMM8 9'hA1
|
||
`define LDY_ABS 9'hAC
|
||
`define LDY_ABSX 9'hBC
|
||
|
||
`define STX_ZP 9'h86
|
||
`define STX_ZPX 9'h96
|
||
`define STX_ZPY 9'h96
|
||
`define STX_ABS 9'h8E
|
||
|
||
`define STY_ZP 9'h84
|
||
`define STY_ZPX 9'h94
|
||
`define STY_ABS 9'h8C
|
||
|
||
`define STZ_ZP 9'h64
|
||
`define STZ_ZPX 9'h74
|
||
`define STZ_ABS 9'h9C
|
||
`define STZ_ABSX 9'h9E
|
||
|
||
`define CPX_IMM 9'hE0
|
||
`define CPX_IMM32 9'hE0
|
||
`define CPX_IMM8 9'hE2
|
||
`define CPX_ZP 9'hE4
|
||
`define CPX_ZPX 9'hE4
|
||
`define CPX_ABS 9'hEC
|
||
`define CPY_IMM 9'hC0
|
||
`define CPY_IMM32 9'hC0
|
||
`define CPY_IMM8 9'hC1
|
||
`define CPY_ZP 9'hC4
|
||
`define CPY_ZPX 9'hC4
|
||
`define CPY_ABS 9'hCC
|
||
|
||
`define TRB_ZP 9'h14
|
||
`define TRB_ZPX 9'h14
|
||
`define TRB_ABS 9'h1C
|
||
`define TSB_ZP 9'h04
|
||
`define TSB_ZPX 9'h04
|
||
`define TSB_ABS 9'h0C
|
||
|
||
`define MVP 9'h44
|
||
`define MVN 9'h54
|
||
`define STS 9'h64
|
||
|
||
// Page Two Opcodes
|
||
`define PG2 9'h42
|
||
|
||
`define ICOFF 9'h108
|
||
`define ICON 9'h128
|
||
`define TOFF 9'h118
|
||
`define TON 9'h138
|
||
`define MUL_IMM8 9'h105
|
||
`define MUL_IMM16 9'h119
|
||
`define MUL_IMM32 9'h109
|
||
`define MULS_IMM8 9'h125
|
||
`define MULS_IMM16 9'h139
|
||
`define MULS_IMM32 9'h129
|
||
`define DIV_IMM8 9'h145
|
||
`define DIV_IMM16 9'h159
|
||
`define DIV_IMM32 9'h149
|
||
`define DIVS_IMM8 9'h165
|
||
`define DIVS_IMM16 9'h179
|
||
`define DIVS_IMM32 9'h169
|
||
`define MOD_IMM8 9'h185
|
||
`define MOD_IMM16 9'h199
|
||
`define MOD_IMM32 9'h189
|
||
`define MODS_IMM8 9'h1A5
|
||
`define MODS_IMM16 9'h1B9
|
||
`define MODS_IMM32 9'h1A9
|
||
`define PUSHA 9'h10B
|
||
`define POPA 9'h12B
|
||
`define BMS_ZPX 9'h106
|
||
`define BMS_ABS 9'h10E
|
||
`define BMS_ABSX 9'h11E
|
||
`define BMC_ZPX 9'h126
|
||
`define BMC_ABS 9'h12E
|
||
`define BMC_ABSX 9'h13E
|
||
`define BMF_ZPX 9'h146
|
||
`define BMF_ABS 9'h14E
|
||
`define BMF_ABSX 9'h15E
|
||
`define BMT_ZPX 9'h166
|
||
`define BMT_ABS 9'h16E
|
||
`define BMT_ABSX 9'h17E
|
||
`define HOFF 9'h158
|
||
`define CMPS 9'h144
|
||
`define SPL_ABS 9'h18E
|
||
`define SPL_ABSX 9'h19E
|
||
|
||
`define LEA_ZPX 9'h1D5
|
||
`define LEA_IX 9'h1C1
|
||
`define LEA_IY 9'h1D1
|
||
`define LEA_ABS 9'h1CD
|
||
`define LEA_ABSX 9'h1DD
|
||
`define LEA_RIND 9'h1D2
|
||
`define LEA_I 9'h1D2
|
||
`define LEA_DSP 9'h1C3
|
||
|
||
`define NOTHING 5'd0
|
||
`define SR_70 5'd1
|
||
`define SR_310 5'd2
|
||
`define BYTE_70 5'd3
|
||
`define WORD_310 5'd4
|
||
`define PC_70 5'd5
|
||
`define PC_158 5'd6
|
||
`define PC_2316 5'd7
|
||
`define PC_3124 5'd8
|
||
`define PC_310 5'd9
|
||
`define WORD_311 5'd10
|
||
`define IA_310 5'd11
|
||
`define IA_70 5'd12
|
||
`define IA_158 5'd13
|
||
`define BYTE_71 5'd14
|
||
`define WORD_312 5'd15
|
||
`define WORD_313 5'd16
|
||
`define WORD_314 5'd17
|
||
`define IA_2316 5'd18
|
||
`define HALF_70 5'd19
|
||
`define HALF_158 5'd20
|
||
`define HALF_71 5'd21
|
||
`define HALF_159 5'd22
|
||
`define HALF_71S 5'd23
|
||
`define HALF_159S 5'd24
|
||
`define BYTE_72 5'd25
|
||
`define TRIP_2316 5'd26
|
||
|
||
`define STW_DEF 6'h0
|
||
`define STW_RES8 6'd14
|
||
`define STW_R4 6'd15
|
||
`define STW_ACC8 6'd16
|
||
`define STW_X8 6'd17
|
||
`define STW_Y8 6'd18
|
||
`define STW_PC3124 6'd19
|
||
`define STW_PC2316 6'd20
|
||
`define STW_PC158 6'd21
|
||
`define STW_PC70 6'd22
|
||
`define STW_SR70 6'd23
|
||
`define STW_Z8 6'd24
|
||
`define STW_DEF8 6'd25
|
||
`define STW_DEF70 6'd26
|
||
`define STW_DEF158 6'd27
|
||
`define STW_DEF2316 6'd28
|
||
|
||
`define STW_ACC70 6'd32
|
||
`define STW_ACC158 6'd33
|
||
`define STW_X70 6'd34
|
||
`define STW_X158 6'd35
|
||
`define STW_Y70 6'd36
|
||
`define STW_Y158 6'd37
|
||
`define STW_Z70 6'd38
|
||
`define STW_Z158 6'd39
|
||
`define STW_DBR 6'd40
|
||
`define STW_DPR158 6'd41
|
||
`define STW_DPR70 6'd42
|
||
`define STW_TMP158 6'd43
|
||
`define STW_TMP70 6'd44
|
||
`define STW_IA158 6'd45
|
||
`define STW_IA70 6'd46
|
||
`define STW_BRA 6'd47
|
||
|
||
// Input Frequency is 32 times the 00 clock
|
||
|
||
module FT816(rst, clk, clko, cyc, phi11, phi12, phi81, phi82, nmi, irq, abort, e, mx, rdy, be, vpa, vda, mlb, vpb, rw, ad, db, dw, err_i, rty_i);
|
||
parameter SUPPORT_TRIBYTES = 1'b0;
|
||
parameter STORE_SKIPPING = 1'b1;
|
||
parameter EXTRA_LONG_BRANCHES = 1'b1;
|
||
parameter RESET1 = 6'd0;
|
||
parameter IFETCH1 = 6'd1;
|
||
parameter IFETCH2 = 6'd2;
|
||
parameter IFETCH3 = 6'd3;
|
||
parameter IFETCH4 = 6'd4;
|
||
parameter DECODE1 = 6'd5;
|
||
parameter DECODE2 = 6'd6;
|
||
parameter DECODE3 = 6'd7;
|
||
parameter DECODE4 = 6'd8;
|
||
parameter STORE1 = 6'd9;
|
||
parameter STORE2 = 6'd10;
|
||
parameter JSR161 = 6'd11;
|
||
parameter RTS1 = 6'd12;
|
||
parameter IY3 = 6'd13;
|
||
parameter BSR1 = 6'd14;
|
||
parameter BYTE_IX5 = 6'd15;
|
||
parameter BYTE_IY5 = 6'd16;
|
||
parameter WAIT_DHIT = 6'd17;
|
||
parameter BYTE_CALC = 6'd18;
|
||
parameter BUS_ERROR = 6'd19;
|
||
parameter LOAD_MAC1 = 6'd20;
|
||
parameter LOAD_MAC2 = 6'd21;
|
||
parameter LOAD_MAC3 = 6'd22;
|
||
parameter MVN3 = 6'd23;
|
||
parameter IFETCH0 = 6'd24;
|
||
parameter LOAD_DCACHE = 6'd26;
|
||
parameter LOAD_ICACHE = 6'd27;
|
||
parameter LOAD_IBUF1 = 6'd28;
|
||
parameter LOAD_IBUF2 = 6'd29;
|
||
parameter LOAD_IBUF3 = 6'd30;
|
||
parameter ICACHE1 = 6'd31;
|
||
parameter IBUF1 = 6'd32;
|
||
parameter DCACHE1 = 6'd33;
|
||
parameter HALF_CALC = 6'd35;
|
||
parameter MVN816 = 6'd36;
|
||
|
||
input rst;
|
||
input clk;
|
||
output clko;
|
||
output reg [4:0] cyc;
|
||
output phi11;
|
||
output phi12;
|
||
output phi81;
|
||
output phi82;
|
||
input nmi;
|
||
input irq;
|
||
input abort;
|
||
output e;
|
||
output mx;
|
||
input rdy;
|
||
input be;
|
||
output reg vpa;
|
||
output reg vda;
|
||
output reg mlb;
|
||
output reg vpb;
|
||
output tri rw;
|
||
output tri [23:0] ad;
|
||
input [7:0] db;
|
||
output[7:0] dw;
|
||
input err_i;
|
||
input rty_i;
|
||
|
||
parameter TRUE = 1'b1;
|
||
parameter FALSE = 1'b0;
|
||
|
||
reg [31:0] phi1r,phi2r;
|
||
reg rwo;
|
||
reg [23:0] ado;
|
||
reg [7:0] dbo;
|
||
|
||
reg [7:0] dbi;
|
||
reg pg2;
|
||
reg [5:0] state;
|
||
reg [5:0] retstate;
|
||
reg [31:0] ir;
|
||
wire [8:0] ir9 = {pg2,ir[7:0]};
|
||
reg [23:0] pc,opc;
|
||
reg [15:0] dpr; // direct page register
|
||
reg [7:0] dbr; // data bank register
|
||
reg [15:0] x,y,acc,sp;
|
||
reg [15:0] tmp;
|
||
wire [15:0] acc16 = acc;
|
||
wire [7:0] acc8=acc[7:0];
|
||
wire [7:0] x8=x[7:0];
|
||
wire [7:0] y8=y[7:0];
|
||
wire [15:0] x16 = x[15:0];
|
||
wire [15:0] y16 = y[15:0];
|
||
wire [15:0] acc_dec = acc - 16'd1;
|
||
wire [15:0] acc_inc = acc + 16'd1;
|
||
wire [15:0] x_dec = x - 16'd1;
|
||
wire [15:0] x_inc = x + 16'd1;
|
||
wire [15:0] y_dec = y - 16'd1;
|
||
wire [15:0] y_inc = y + 16'd1;
|
||
wire [15:0] sp_dec = sp - 16'd1;
|
||
wire [15:0] sp_inc = sp + 16'd1;
|
||
wire [15:0] sp_dec2 = sp - 16'd2;
|
||
reg gie; // global interrupt enable (set when sp is loaded)
|
||
reg hwi; // hardware interrupt indicator
|
||
reg im;
|
||
reg cf,vf,nf,zf,df,em,bf;
|
||
reg m816;
|
||
reg x_bit,m_bit;
|
||
wire m16 = m816 & ~m_bit;
|
||
wire xb16 = m816 & ~x_bit;
|
||
wire [7:0] sr8 = m816 ? {nf,vf,m_bit,x_bit,df,im,zf,cf} : {nf,vf,1'b0,bf,df,im,zf,cf};
|
||
reg nmi1,nmi_edge;
|
||
reg wai;
|
||
reg [7:0] b8;
|
||
reg [15:0] b16;
|
||
reg [7:0] b24;
|
||
reg [8:0] res8;
|
||
reg [16:0] res16;
|
||
wire resc8 = res8[8];
|
||
wire resc16 = res16[16];
|
||
wire resz8 = ~|res8[7:0];
|
||
wire resz16 = ~|res16[15:0];
|
||
wire resn8 = res8[7];
|
||
wire resn16 = res16[15];
|
||
reg [23:0] radr;
|
||
reg [23:0] wadr;
|
||
reg [23:0] wdat;
|
||
wire [7:0] rdat;
|
||
reg [4:0] load_what;
|
||
reg [5:0] store_what;
|
||
reg [15:0] tmp16;
|
||
reg first_ifetch;
|
||
reg [23:0] derr_address;
|
||
|
||
reg [8:0] intno;
|
||
reg isBusErr;
|
||
reg isBrk,isMove,isSts;
|
||
reg isMove816;
|
||
reg isRTI,isRTL,isRTS;
|
||
reg isRMW;
|
||
reg isSub;
|
||
reg isJsrIndx,isJsrInd;
|
||
reg isIY,isIY24,isI24;
|
||
reg isTribyte;
|
||
|
||
wire isCmp = ir9==`CPX_ZPX || ir9==`CPX_ABS ||
|
||
ir9==`CPY_ZPX || ir9==`CPY_ABS;
|
||
wire isRMW8 =
|
||
ir9==`ASL_ZP || ir9==`ROL_ZP || ir9==`LSR_ZP || ir9==`ROR_ZP || ir9==`INC_ZP || ir9==`DEC_ZP ||
|
||
ir9==`ASL_ZPX || ir9==`ROL_ZPX || ir9==`LSR_ZPX || ir9==`ROR_ZPX || ir9==`INC_ZPX || ir9==`DEC_ZPX ||
|
||
ir9==`ASL_ABS || ir9==`ROL_ABS || ir9==`LSR_ABS || ir9==`ROR_ABS || ir9==`INC_ABS || ir9==`DEC_ABS ||
|
||
ir9==`ASL_ABSX || ir9==`ROL_ABSX || ir9==`LSR_ABSX || ir9==`ROR_ABSX || ir9==`INC_ABSX || ir9==`DEC_ABSX ||
|
||
ir9==`TRB_ZP || ir9==`TRB_ZPX || ir9==`TRB_ABS || ir9==`TSB_ZP || ir9==`TSB_ZPX || ir9==`TSB_ABS;
|
||
wire isBranch = ir9==`BRA || ir9==`BEQ || ir9==`BNE || ir9==`BVS || ir9==`BVC || ir9==`BMI || ir9==`BPL || ir9==`BCS || ir9==`BCC;
|
||
|
||
// Registerable decodes
|
||
// The following decodes can be registered because they aren't needed until at least the cycle after
|
||
// the DECODE stage.
|
||
|
||
always @(posedge clk)
|
||
if (state==RESET1)
|
||
isBrk <= `TRUE;
|
||
else if (state==DECODE1||state==DECODE2||state==DECODE3||state==DECODE4) begin
|
||
isRMW <= isRMW8;
|
||
isRTI <= ir9==`RTI;
|
||
isRTL <= ir9==`RTL;
|
||
isRTS <= ir9==`RTS;
|
||
isBrk <= ir9==`BRK || ir9==`COP;
|
||
isMove <= ir9==`MVP || ir9==`MVN;
|
||
isJsrIndx <= ir9==`JSR_INDX;
|
||
isJsrInd <= ir9==`JSR_IND;
|
||
end
|
||
|
||
assign mx = clk ? m_bit : x_bit;
|
||
assign e = ~m816;
|
||
|
||
wire [15:0] bcaio;
|
||
wire [15:0] bcao;
|
||
wire [15:0] bcsio;
|
||
wire [15:0] bcso;
|
||
wire bcaico,bcaco,bcsico,bcsco;
|
||
wire bcaico8,bcaco8,bcsico8,bcsco8;
|
||
|
||
`ifdef SUPPORT_BCD
|
||
BCDAdd4 ubcdai1 (.ci(cf),.a(acc16),.b(ir[23:8]),.o(bcaio),.c(bcaico),.c8(bcaico8));
|
||
BCDAdd4 ubcda2 (.ci(cf),.a(acc16),.b(b8),.o(bcao),.c(bcaco),.c8(bcaco8));
|
||
BCDSub4 ubcdsi1 (.ci(cf),.a(acc16),.b(ir[23:8]),.o(bcsio),.c(bcsico),.c8(bcsico8));
|
||
BCDSub4 ubcds2 (.ci(cf),.a(acc16),.b(b8),.o(bcso),.c(bcsco),.c8(bcsco8));
|
||
`endif
|
||
|
||
wire [7:0] dati = db;
|
||
|
||
// Evaluate branches
|
||
//
|
||
reg takb;
|
||
always @(ir9 or cf or vf or nf or zf)
|
||
case(ir9)
|
||
`BEQ: takb <= zf;
|
||
`BNE: takb <= !zf;
|
||
`BPL: takb <= !nf;
|
||
`BMI: takb <= nf;
|
||
`BCS: takb <= cf;
|
||
`BCC: takb <= !cf;
|
||
`BVS: takb <= vf;
|
||
`BVC: takb <= !vf;
|
||
`BRA: takb <= 1'b1;
|
||
`BRL: takb <= 1'b1;
|
||
default: takb <= 1'b0;
|
||
endcase
|
||
|
||
reg [23:0] ia;
|
||
wire [23:0] mvnsrc_address = {ir[23:16],x16};
|
||
wire [23:0] mvndst_address = {ir[15: 8],y16};
|
||
wire [23:0] iapy8 = ia + y16; // Don't add in abs8, already included with ia
|
||
wire [23:0] zp_address = {8'h00,ir[15:8]} + dpr;
|
||
wire [23:0] zpx_address = {{16'h00,ir[15:8]} + x16} + dpr;
|
||
wire [23:0] zpy_address = {{16'h00,ir[15:8]} + y16} + dpr;
|
||
wire [23:0] abs_address = {dbr,ir[23:8]};
|
||
wire [23:0] absx_address = {dbr,ir[23:8] + x16}; // simulates 64k bank wrap-around
|
||
wire [23:0] absy_address = {dbr,ir[23:8] + y16};
|
||
wire [23:0] al_address = {ir[31:8]};
|
||
wire [23:0] alx_address = {ir[31:8] + x16};
|
||
|
||
wire [23:0] dsp_address = m816 ? {8'h00,sp + ir[15:8]} : {16'h0001,sp[7:0]+ir[15:8]};
|
||
reg [23:0] vect;
|
||
|
||
assign rw = be ? rwo : 1'bz;
|
||
assign ad = be ? ado : {24{1'bz}};
|
||
assign dw = rwo ? {8{1'bz}} : be ? dbo : {8{1'bz}};
|
||
|
||
reg [31:0] phi11r,phi12r,phi81r,phi82r;
|
||
assign phi11 = phi11r[31];
|
||
assign phi12 = phi12r[31];
|
||
assign phi81 = phi81r[31];
|
||
assign phi82 = phi82r[31];
|
||
|
||
always @(posedge clk)
|
||
if (~rst) begin
|
||
cyc <= 5'd0;
|
||
phi11r <= 32'b01111111111111100000000000000000;
|
||
phi12r <= 32'b00000000000000000111111111111110;
|
||
phi81r <= 32'b01110000011100000111000001110000;
|
||
phi82r <= 32'b00000111000001110000011100000111;
|
||
end
|
||
else begin
|
||
cyc <= cyc + 5'd1;
|
||
phi11r <= {phi11r[30:0],phi11r[31]};
|
||
phi12r <= {phi12r[30:0],phi12r[31]};
|
||
phi81r <= {phi81r[30:0],phi81r[31]};
|
||
phi82r <= {phi82r[30:0],phi82r[31]};
|
||
end
|
||
|
||
// Detect a single byte opcode
|
||
function isOneByte;
|
||
input [7:0] ir;
|
||
casex(ir)
|
||
8'hx8: isOneByte = TRUE;
|
||
8'hxA: isOneByte = TRUE;
|
||
8'hxB: isOneByte = TRUE;
|
||
`RTI,`RTS: isOneByte = TRUE;
|
||
default: isOneByte = FALSE;
|
||
endcase
|
||
endfunction
|
||
|
||
// Detect double byte opcode
|
||
function isTwoBytes;
|
||
input [7:0] ir;
|
||
input m16;
|
||
input xb16;
|
||
casex(ir)
|
||
`BRK,`COP: isTwoBytes = TRUE;
|
||
8'hx1: isTwoBytes = TRUE;
|
||
8'hx3: isTwoBytes = TRUE;
|
||
8'hx5: isTwoBytes = TRUE;
|
||
8'hx6: isTwoBytes = TRUE;
|
||
8'hx7: isTwoBytes = TRUE;
|
||
`BPL,`BMI,`BVS,`BVC,`BCS,`BCC,`BEQ,`BNE,`BRA: isTwoBytes = TRUE;
|
||
`LDY_IMM,`CPY_IMM,`CPX_IMM,`LDX_IMM: isTwoBytes = !xb16;
|
||
`ORA_I,`AND_I,`EOR_I,`LDA_I,`CMP_I,`STA_I,`ADC_I,`SBC_I,`PEI:
|
||
isTwoBytes = TRUE;
|
||
`REP,`SEP: isTwoBytes = TRUE;
|
||
`TSB_ZPX,`TRB_ZPX,`BIT_ZP,`BIT_ZPX,`STZ_ZP,`STZ_ZPX,`STY_ZP,`STY_ZPX,
|
||
`LDY_ZP,`LDY_ZPX,`CPY_ZP,`CPX_ZP:
|
||
isTwoBytes = TRUE;
|
||
`ORA_IMM,`AND_IMM,`EOR_IMM,`ADC_IMM,`SBC_IMM,`CMP_IMM,`LDA_IMM,`BIT_IMM:
|
||
isTwoBytes = !m16;
|
||
default: isTwoBytes = FALSE;
|
||
endcase
|
||
endfunction
|
||
|
||
function isThreeBytes;
|
||
input [7:0] ir;
|
||
input m16;
|
||
input xb16;
|
||
casex(ir)
|
||
`JSR: isThreeBytes = TRUE;
|
||
`PER,`BRL: isThreeBytes = TRUE;
|
||
`MVP,`MVN,`PEA: isThreeBytes = TRUE;
|
||
`LDY_IMM,`CPY_IMM,`CPX_IMM,`LDX_IMM: isThreeBytes = xb16;
|
||
`ORA_IMM,`AND_IMM,`EOR_IMM,`ADC_IMM,`SBC_IMM,`CMP_IMM,`LDA_IMM,`BIT_IMM:
|
Also available in: Unified diff
First cut implementation of veronica clone for ultimate cart - does not work yet, but getting close. Project to try out Rob Finchs 65816 core.