1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-10 20:33:41 +00:00

add new SID

This commit is contained in:
Gehstock
2018-09-04 11:08:11 +02:00
parent 1f94ae77d9
commit 0f1f96c3df
40 changed files with 20780 additions and 200 deletions

View File

@@ -41,9 +41,8 @@
# ========================
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:40:24 MAY 17, 2014"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name FLOW_ENABLE_IO_ASSIGNMENT_ANALYSIS ON
@@ -312,59 +311,53 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to CONF_DATA0
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(C64_MiST)
# ----------------------
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name VERILOG_FILE rtl/1541/trkbuf.v
set_global_assignment -name VHDL_FILE rtl/1541/rom_C1541.vhd
set_global_assignment -name VHDL_FILE rtl/1541/c1541_sd.vhd
set_global_assignment -name VHDL_FILE rtl/1541/c1541_rom.vhd
set_global_assignment -name VHDL_FILE rtl/1541/c1541_logic.vhd
set_global_assignment -name VHDL_FILE rtl/c64_mist.vhd
set_global_assignment -name VHDL_FILE rtl/sid/wave_map.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_top.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_regs.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_mixer.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_filter.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_debug_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/sid/sid_ctrl.vhd
set_global_assignment -name VHDL_FILE rtl/sid/Q_table.vhd
set_global_assignment -name VHDL_FILE rtl/sid/oscillator.vhd
set_global_assignment -name VHDL_FILE rtl/sid/my_math_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/sid/mult_acc.vhd
set_global_assignment -name VHDL_FILE rtl/sid/adsr_multi.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_sid_iec.vhd
set_global_assignment -name VHDL_FILE rtl/video_vicII_656x_e.vhd
set_global_assignment -name VHDL_FILE rtl/video_vicII_656x_a.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VERILOG_FILE rtl/trkbuf.v
set_global_assignment -name VERILOG_FILE rtl/sigma_delta_dac.v
set_global_assignment -name VERILOG_FILE rtl/sdram.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sd_card.sv
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
set_global_assignment -name VHDL_FILE rtl/rom_C1541.vhd
set_global_assignment -name VHDL_FILE rtl/rom_c64_chargen.vhd
set_global_assignment -name VHDL_FILE rtl/rom_C64.vhd
set_global_assignment -name VHDL_FILE rtl/pll.vhd
set_global_assignment -name VERILOG_FILE rtl/osd.v
set_global_assignment -name VERILOG_FILE rtl/mist_io.v
set_global_assignment -name VHDL_FILE rtl/m6522.vhd
set_global_assignment -name VHDL_FILE rtl/io_ps2_keyboard.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/gcr_floppy.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_sid_iec.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_rgbcolor.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_keyboard_matrix_mark_mcdougall.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_bustiming.vhd
set_global_assignment -name VHDL_FILE rtl/fpga64_buslogic_roms_mmu.vhd
set_global_assignment -name VHDL_FILE rtl/cpu65xx_fast.vhd
set_global_assignment -name VHDL_FILE rtl/cpu65xx_e.vhd
set_global_assignment -name VHDL_FILE rtl/cpu_6510.vhd
set_global_assignment -name VHDL_FILE rtl/composite_sync.vhd
set_global_assignment -name VHDL_FILE rtl/cia6526.vhd
set_global_assignment -name VHDL_FILE rtl/cpu_6510.vhd
set_global_assignment -name VHDL_FILE rtl/m6522.vhd
set_global_assignment -name VERILOG_FILE rtl/cartridge.v
set_global_assignment -name VHDL_FILE rtl/c1541_sd.vhd
set_global_assignment -name VHDL_FILE rtl/c1541_logic.vhd
set_global_assignment -name VHDL_FILE rtl/rom_c64_chargen.vhd
set_global_assignment -name VHDL_FILE rtl/rom_C64.vhd
set_global_assignment -name VHDL_FILE rtl/rom_GS64.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sid8580.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sid_voice.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sid_filters.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sid_envelope.sv
set_global_assignment -name VERILOG_FILE rtl/sigma_delta_dac.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VERILOG_FILE rtl/sdram.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sd_card.sv
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
set_global_assignment -name VHDL_FILE rtl/pll.vhd
set_global_assignment -name VERILOG_FILE rtl/osd.v
set_global_assignment -name VERILOG_FILE rtl/mist_io.v
set_global_assignment -name VHDL_FILE rtl/io_ps2_keyboard.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd
set_global_assignment -name VHDL_FILE rtl/composite_sync.vhd
set_global_assignment -name TEXT_FILE ../Text1.txt
set_global_assignment -name VHDL_FILE rtl/1541/gcr_floppy.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -0,0 +1,6 @@
{ "" "" "" "Verilog HDL macro warning at hq2x.sv(26): overriding existing definition for macro \"BITS_TO_FIT\", which was defined in \"rtl/scandoubler.v\", line 109" { } { } 0 10274 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "Verilog HDL warning at hq2x.sv(247): extended using \"x\" or \"z\"" { } { } 0 10273 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "Verilog HDL information at scandoubler.v(102): always construct contains both blocking and non-blocking assignments" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "2 hierarchies have connectivity warnings - see the Connectivity Checks report folder" { } { } 0 12241 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "*" { } { } 0 332060 "" 0 0 "Quartus II" 0 -1 0 ""}

View File

@@ -0,0 +1,51 @@
library ieee;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.ALL;
use IEEE.numeric_std.all;
entity c1541_rom is
port
(
wrclock : in std_logic;
wraddress : in std_logic_vector(13 downto 0);
data : in std_logic_vector(7 downto 0);
wren : in std_logic := '0';
rdclock : in std_logic;
rdaddress : in std_logic_vector(13 downto 0);
q : out std_logic_vector(7 downto 0)
);
end;
architecture rtl of c1541_rom is
subtype word_t is std_logic_vector(7 downto 0);
type memory_t is array(16383 downto 0) of word_t;
shared variable ram : memory_t;
attribute ram_init_file : string;
attribute ram_init_file of ram : variable is "c1541/c1541_rom.mif";
begin
-- Port A
process(wrclock)
begin
if(rising_edge(wrclock)) then
if(wren = '1') then
ram(to_integer(unsigned(wraddress))) := data;
end if;
end if;
end process;
-- Port B
process(rdclock)
begin
if(rising_edge(rdclock)) then
q <= ram(to_integer(unsigned(rdaddress)));
end if;
end process;
end rtl;

View File

@@ -0,0 +1,18 @@
set_global_assignment -name VHDL_FILE c1541/cpu/shifter.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/proc_registers.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/proc_interrupt.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/proc_control.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/pkg_6502_opcodes.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/pkg_6502_defs.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/pkg_6502_decode.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/implied.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/data_oper.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/bit_cpx_cpy.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/alu.vhd
set_global_assignment -name VHDL_FILE c1541/cpu/proc_core.vhd
set_global_assignment -name VHDL_FILE c1541/c1541_via6522.vhd
set_global_assignment -name VHDL_FILE c1541/c1541_rom.vhd
set_global_assignment -name VHDL_FILE c1541/gcr_floppy.vhd
set_global_assignment -name SYSTEMVERILOG_FILE c1541/c1541_track.sv
set_global_assignment -name VHDL_FILE c1541/c1541_logic.vhd
set_global_assignment -name VHDL_FILE c1541/c1541_sd.vhd

View File

@@ -0,0 +1,301 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
--
-- Model 1541B
--
entity c1541_logic is
port
(
clk_32M : in std_logic;
reset : in std_logic;
-- serial bus
sb_data_oe : out std_logic;
sb_data_in : in std_logic;
sb_clk_oe : out std_logic;
sb_clk_in : in std_logic;
sb_atn_in : in std_logic;
c1541rom_clk : in std_logic;
c1541rom_addr : in std_logic_vector(13 downto 0);
c1541rom_data : in std_logic_vector(7 downto 0);
c1541rom_wr : in std_logic;
-- drive-side interface
ds : in std_logic_vector(1 downto 0); -- device select
di : in std_logic_vector(7 downto 0); -- disk read data
do : out std_logic_vector(7 downto 0); -- disk write data
mode : out std_logic; -- read/write
stp : out std_logic_vector(1 downto 0); -- stepper motor control
mtr : out std_logic; -- stepper motor on/off
freq : out std_logic_vector(1 downto 0); -- motor frequency
sync_n : in std_logic; -- reading SYNC bytes
byte_n : in std_logic; -- byte ready
wps_n : in std_logic; -- write-protect sense
tr00_sense_n : in std_logic; -- track 0 sense (unused?)
act : out std_logic -- activity LED
);
end c1541_logic;
architecture SYN of c1541_logic is
-- clocks
signal p2_h_r : std_logic;
signal p2_h_f : std_logic;
-- cpu signals
signal cpu_a : std_logic_vector(16 downto 0);
signal cpu_di : std_logic_vector(7 downto 0);
signal cpu_do : std_logic_vector(7 downto 0);
signal cpu_rw : std_logic;
signal cpu_irq_n : std_logic;
signal cpu_so_n : std_logic;
-- rom signals
signal rom_cs : std_logic;
signal rom_do : std_logic_vector(cpu_di'range);
-- ram signals
signal ram_cs : std_logic;
signal ram_wr : std_logic;
signal ram_do : std_logic_vector(cpu_di'range);
-- UC1 (VIA6522) signals
signal uc1_do : std_logic_vector(7 downto 0);
signal uc1_cs : std_logic;
signal uc1_irq_n : std_logic;
signal uc1_pa_i : std_logic_vector(7 downto 0) := (others => '0');
signal uc1_pb_i : std_logic_vector(7 downto 0) := (others => '0');
signal uc1_pb_o : std_logic_vector(7 downto 0);
signal uc1_pb_oe_n : std_logic_vector(7 downto 0);
-- UC3 (VIA6522) signals
signal uc3_do : std_logic_vector(7 downto 0);
signal uc3_cs : std_logic;
signal uc3_irq_n : std_logic;
signal uc3_ca1_i : std_logic;
signal uc3_ca2_o : std_logic;
signal uc3_ca2_oe_n : std_logic;
signal uc3_pa_i : std_logic_vector(7 downto 0);
signal uc3_pa_o : std_logic_vector(7 downto 0);
signal uc3_cb2_o : std_logic;
signal uc3_cb2_oe_n : std_logic;
signal uc3_pa_oe_n : std_logic_vector(7 downto 0);
signal uc3_pb_i : std_logic_vector(7 downto 0);
signal uc3_pb_o : std_logic_vector(7 downto 0);
signal uc3_pb_oe_n : std_logic_vector(7 downto 0);
-- internal signals
signal atna : std_logic; -- ATN ACK - input gate array
signal atn : std_logic; -- attention
signal soe : std_logic; -- set overflow enable
type t_byte_array is array(2047 downto 0) of std_logic_vector(7 downto 0);
signal ram : t_byte_array;
signal sb_data : std_logic;
signal sb_clk : std_logic;
signal iec_atn_d1 : std_logic;
signal iec_data_d1 : std_logic;
signal iec_clk_d1 : std_logic;
signal iec_atn_d2 : std_logic;
signal iec_data_d2 : std_logic;
signal iec_clk_d2 : std_logic;
signal iec_atn : std_logic;
signal iec_data : std_logic;
signal iec_clk : std_logic;
begin
process (clk_32M) begin
if rising_edge(clk_32M) then
iec_atn_d1 <=sb_atn_in;
iec_atn_d2 <=iec_atn_d1;
iec_atn <=iec_atn_d2;
iec_data_d1<=sb_data_in;
iec_data_d2<=iec_data_d1;
iec_data <=iec_data_d2;
iec_clk_d1 <=sb_clk_in;
iec_clk_d2 <=iec_clk_d1;
iec_clk <=iec_clk_d2;
end if;
end process;
process (clk_32M, reset)
variable count : std_logic_vector(4 downto 0) := (others => '0');
begin
if rising_edge(clk_32M) then
count := std_logic_vector(unsigned(count) + 1);
p2_h_r <= '0'; if count = "00000" then p2_h_r <= '1'; end if;
p2_h_f <= '0'; if count = "10000" then p2_h_f <= '1'; end if;
end if;
end process;
-- decode logic
ram_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "00000-----------") else '0'; -- RAM $0000-$07FF (2KB)
uc1_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "000110000000----") else '0'; -- UC1 $1800-$180F
uc3_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "000111000000----") else '0'; -- UC3 $1C00-$1C0F
rom_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "11--------------") else '0'; -- ROM $C000-$FFFF (16KB)
-- qualified write signals
ram_wr <= '1' when ram_cs = '1' and cpu_rw = '0' else '0';
--
-- hook up UC1 ports
--
sb_data <= (uc1_pb_o(1) and not uc1_pb_oe_n(1)) or atn;
sb_clk <= uc1_pb_o(3) and not uc1_pb_oe_n(3);
atna <= uc1_pb_o(4);
uc1_pa_i(0) <= tr00_sense_n;
uc1_pb_i(0) <= not iec_data or sb_data;
uc1_pb_i(2) <= not iec_clk or sb_clk;
uc1_pb_i(7) <= not iec_atn;
uc1_pb_i(6 downto 5) <= ds;
sb_data_oe <= sb_data;
sb_clk_oe <= sb_clk;
--
-- hook up UC3 ports
--
uc3_ca1_i <= cpu_so_n; -- byte ready gated with soe
soe <= uc3_ca2_o or uc3_ca2_oe_n;
uc3_pa_i <= di;
do <= uc3_pa_o or uc3_pa_oe_n;
mode <= uc3_cb2_o or uc3_cb2_oe_n;
stp(1) <= uc3_pb_o(0) or uc3_pb_oe_n(0);
stp(0) <= uc3_pb_o(1) or uc3_pb_oe_n(1);
mtr <= uc3_pb_o(2) or uc3_pb_oe_n(2);
act <= uc3_pb_o(3) or uc3_pb_oe_n(3);
freq <= uc3_pb_o(6 downto 5) or uc3_pb_oe_n(6 downto 5);
uc3_pb_i <= sync_n & "11" & wps_n & "1111";
--
-- CPU connections
--
cpu_di <= rom_do when rom_cs = '1' else
ram_do when ram_cs = '1' else
uc1_do when uc1_cs = '1' else
uc3_do when uc3_cs = '1' else
(others => '1');
cpu_irq_n <= uc1_irq_n and uc3_irq_n;
cpu_so_n <= byte_n or not soe;
-- internal connections
atn <= atna xor (not sb_atn_in);
cpu: work.proc_core
port map(
reset => reset,
clock_en => p2_h_f,
clock => clk_32M,
so_n => cpu_so_n,
irq_n => cpu_irq_n,
read_write_n => cpu_rw,
addr_out => cpu_a,
data_in => cpu_di,
data_out => cpu_do
);
rom_inst: entity work.C1541_rom
port map (
wrclock => c1541rom_clk,
wren => c1541rom_wr,
data => c1541rom_data,
wraddress => c1541rom_addr,
rdclock => clk_32M,
rdaddress => cpu_a(13 downto 0),
q => rom_do
);
process (clk_32M)
begin
if rising_edge(clk_32M) then
ram_do <= ram(to_integer(unsigned(cpu_a(13 downto 0))));
if ram_wr = '1' then
ram(to_integer(unsigned(cpu_a(13 downto 0)))) <= cpu_do;
end if;
end if;
end process;
uc1_via6522_inst : entity work.c1541_via6522
port map
(
addr => cpu_a(3 downto 0),
data_in => cpu_do,
data_out => uc1_do,
ren => cpu_rw and uc1_cs,
wen => not cpu_rw and uc1_cs,
irq_l => uc1_irq_n,
-- port a
ca1_i => not sb_atn_in,
ca2_i => '0',
port_a_i => uc1_pa_i,
-- port b
cb1_i => '0',
cb2_i => '0',
port_b_i => uc1_pb_i,
port_b_o => uc1_pb_o,
port_b_t_l => uc1_pb_oe_n,
reset => reset,
clock => clk_32M,
rising => p2_h_r,
falling => p2_h_f
);
uc3_via6522_inst : entity work.c1541_via6522
port map
(
addr => cpu_a(3 downto 0),
data_in => cpu_do,
data_out => uc3_do,
ren => cpu_rw and uc3_cs,
wen => not cpu_rw and uc3_cs,
irq_l => uc3_irq_n,
-- port a
ca1_i => uc3_ca1_i,
ca2_i => '0',
ca2_o => uc3_ca2_o,
ca2_t_l => uc3_ca2_oe_n,
port_a_i => uc3_pa_i,
port_a_o => uc3_pa_o,
port_a_t_l => uc3_pa_oe_n,
-- port b
cb1_i => '0',
cb2_i => '0',
cb2_o => uc3_cb2_o,
cb2_t_l => uc3_cb2_oe_n,
port_b_i => uc3_pb_i,
port_b_o => uc3_pb_o,
port_b_t_l => uc3_pb_oe_n,
reset => reset,
clock => clk_32M,
rising => p2_h_r,
falling => p2_h_f
);
end SYN;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
library ieee;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.ALL;
use IEEE.numeric_std.all;
entity c1541_rom is
port
(
wrclock : in std_logic;
wraddress : in std_logic_vector(13 downto 0);
data : in std_logic_vector(7 downto 0);
wren : in std_logic := '0';
rdclock : in std_logic;
rdaddress : in std_logic_vector(13 downto 0);
q : out std_logic_vector(7 downto 0)
);
end;
architecture rtl of c1541_rom is
subtype word_t is std_logic_vector(7 downto 0);
type memory_t is array(16383 downto 0) of word_t;
shared variable ram : memory_t;
attribute ram_init_file : string;
attribute ram_init_file of ram : variable is "c1541/c1541_rom.mif";
begin
-- Port A
process(wrclock)
begin
if(rising_edge(wrclock)) then
if(wren = '1') then
ram(to_integer(unsigned(wraddress))) := data;
end if;
end if;
end process;
-- Port B
process(rdclock)
begin
if(rising_edge(rdclock)) then
q <= ram(to_integer(unsigned(rdaddress)));
end if;
end process;
end rtl;

View File

@@ -0,0 +1,279 @@
---------------------------------------------------------------------------------
--
-- Reworked and adapted to MiSTer by Sorgelig@MiSTer (31.08.2018)
--
-- Commodore 1541 to SD card by Dar (darfpga@aol.fr)
-- http://darfpga.blogspot.fr
--
-- c1541_logic from : Mark McDougall
-- via6522 from : Gideon Zweijtzer <gideon.zweijtzer@gmail.com>
-- cpu from : Gideon Zweijtzer <gideon.zweijtzer@gmail.com>
-- c1541_track from : Sorgelig@MiSTer
--
-- c1541_logic modified for : slow down CPU (EOI ack missed by real c64)
-- : remove iec internal OR wired
-- : synched atn_in (sometime no IRQ with real c64)
--
-- Input clk 32MHz
--
---------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.ALL;
use IEEE.numeric_std.all;
entity c1541_sd is
port
(
clk32 : in std_logic;
disk_change : in std_logic;
disk_readonly : in std_logic;
drive_num : in std_logic_vector(1 downto 0) := "00";
iec_reset_i : in std_logic;
iec_atn_i : in std_logic;
iec_data_i : in std_logic;
iec_clk_i : in std_logic;
iec_data_o : out std_logic;
iec_clk_o : out std_logic;
sd_lba : out std_logic_vector(31 downto 0);
sd_rd : out std_logic;
sd_wr : out std_logic;
sd_ack : in std_logic;
sd_buff_addr : in std_logic_vector(8 downto 0);
sd_buff_dout : in std_logic_vector(7 downto 0);
sd_buff_din : out std_logic_vector(7 downto 0);
sd_buff_wr : in std_logic;
led : out std_logic;
c1541rom_clk : in std_logic;
c1541rom_addr : in std_logic_vector(13 downto 0);
c1541rom_data : in std_logic_vector(7 downto 0);
c1541rom_wr : in std_logic
);
end;
architecture struct of c1541_sd is
component c1541_track port
(
sd_lba : out std_logic_vector(31 downto 0);
sd_rd : out std_logic;
sd_wr : out std_logic;
sd_ack : in std_logic;
sd_buff_addr : in std_logic_vector(8 downto 0);
sd_buff_dout : in std_logic_vector(7 downto 0);
sd_buff_din : out std_logic_vector(7 downto 0);
sd_buff_wr : in std_logic;
buff_addr : in std_logic_vector(7 downto 0);
buff_dout : out std_logic_vector(7 downto 0);
buff_din : in std_logic_vector(7 downto 0);
buff_we : in std_logic;
save_track : in std_logic;
change : in std_logic; -- Force reload as disk may have changed
track : in std_logic_vector(5 downto 0); -- Track number (0-34)
sector : in std_logic_vector(4 downto 0); -- Sector number (0-20)
busy : out std_logic;
clk : in std_logic; -- System clock
reset : in std_logic
);
end component;
signal buff_dout : std_logic_vector(7 downto 0);
signal buff_din : std_logic_vector(7 downto 0);
signal buff_we : std_logic;
signal do : std_logic_vector(7 downto 0); -- disk read data
signal di : std_logic_vector(7 downto 0); -- disk write data
signal mode : std_logic; -- read/write
signal stp : std_logic_vector(1 downto 0); -- stepper motor control
signal stp_r : std_logic_vector(1 downto 0); -- stepper motor control
signal mtr : std_logic; -- stepper motor on/off
signal sync_n : std_logic; -- reading SYNC bytes
signal byte_n : std_logic; -- byte ready
signal act : std_logic; -- activity LED
signal act_r : std_logic;
signal sd_busy : std_logic;
signal sector : std_logic_vector(4 downto 0);
signal byte_addr : std_logic_vector(7 downto 0);
signal track_num_dbl : std_logic_vector(6 downto 0);
signal track : std_logic_vector(5 downto 0);
signal tr00_sense_n : std_logic;
signal save_track : std_logic;
signal track_modified : std_logic;
signal ch_timeout : integer := 0;
signal prev_change : std_logic := '0';
signal ch_state : std_logic := '0';
signal reset, reset_r : std_logic;
begin
tr00_sense_n <= '1' when (track > "000000") else '0';
process(clk32) begin
if rising_edge(clk32) then
reset_r <= iec_reset_i;
reset <= reset_r;
end if;
end process;
process(clk32) begin
if rising_edge(clk32) then
prev_change <= disk_change;
if ch_timeout > 0 then
ch_timeout <= ch_timeout - 1;
ch_state <= '1';
else
ch_state <= '0';
end if;
if prev_change = '0' and disk_change = '1' then
ch_timeout <= 15000000;
end if;
end if;
end process;
c1541 : entity work.c1541_logic
port map
(
clk_32M => clk32,
reset => reset,
-- serial bus
sb_data_oe => iec_data_o,
sb_clk_oe => iec_clk_o,
sb_data_in => not iec_data_i,
sb_clk_in => not iec_clk_i,
sb_atn_in => not iec_atn_i,
c1541rom_clk => c1541rom_clk,
c1541rom_addr => c1541rom_addr,
c1541rom_data => c1541rom_data,
c1541rom_wr => c1541rom_wr,
-- drive-side interface
ds => drive_num, -- device select
di => do, -- disk read data
do => di, -- disk write data
mode => mode, -- read/write
stp => stp, -- stepper motor control
mtr => mtr, -- motor on/off
freq => open, -- motor frequency
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
wps_n => (not disk_readonly) xor ch_state, -- write-protect sense
tr00_sense_n => tr00_sense_n, -- track 0 sense
act => act -- activity LED
);
floppy : entity work.gcr_floppy
port map
(
clk32 => clk32,
dout => do, -- disk read data
din => di,
mode => mode,
mtr => mtr, -- stepper motor on/off
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
track => track,
sector => sector,
byte_addr => byte_addr,
ram_do => buff_dout,
ram_di => buff_din,
ram_we => buff_we,
ram_ready => not sd_busy
);
track_buf : c1541_track
port map
(
sd_lba => sd_lba,
sd_rd => sd_rd,
sd_wr => sd_wr,
sd_ack => sd_ack,
sd_buff_addr => sd_buff_addr,
sd_buff_dout => sd_buff_dout,
sd_buff_din => sd_buff_din,
sd_buff_wr => sd_buff_wr,
buff_addr => byte_addr,
buff_dout => buff_dout,
buff_din => buff_din,
buff_we => buff_we,
save_track => save_track,
change => disk_change,
track => track,
sector => sector,
clk => clk32,
reset => reset,
busy => sd_busy
);
led <= act or sd_busy;
process (clk32)
begin
if rising_edge(clk32) then
stp_r <= stp;
act_r <= act;
save_track <= '0';
track <= track_num_dbl(6 downto 1);
if buff_we = '1' then track_modified <= '1'; end if;
if disk_change = '1' then track_modified <= '0'; end if;
if reset = '1' then
track_num_dbl <= "0100100";--"0000010";
track_modified <= '0';
else
if mtr = '1' then
if( (stp_r = "00" and stp = "10")
or (stp_r = "10" and stp = "01")
or (stp_r = "01" and stp = "11")
or (stp_r = "11" and stp = "00")) then
if track_num_dbl < "1010000" then
track_num_dbl <= track_num_dbl + '1';
end if;
save_track <= track_modified;
track_modified <= '0';
end if;
if( (stp_r = "00" and stp = "11")
or (stp_r = "10" and stp = "00")
or (stp_r = "01" and stp = "10")
or (stp_r = "11" and stp = "01")) then
if track_num_dbl > "0000001" then
track_num_dbl <= track_num_dbl - '1';
end if;
save_track <= track_modified;
track_modified <= '0';
end if;
end if;
if act_r = '1' and act = '0' then -- stopping activity
save_track <= track_modified;
track_modified <= '0';
end if;
end if;
end if; -- rising edge clock
end process;
end struct;

View File

@@ -0,0 +1,174 @@
//
// c1541_track
// Copyright (c) 2016 Sorgelig
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the Lesser GNU 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 c1541_track
(
input clk,
input reset,
output [31:0] sd_lba,
output reg sd_rd,
output reg sd_wr,
input sd_ack,
input [8:0] sd_buff_addr,
input [7:0] sd_buff_dout,
output [7:0] sd_buff_din,
input sd_buff_wr,
input save_track,
input change,
input [5:0] track,
input [4:0] sector,
input [7:0] buff_addr,
output [7:0] buff_dout,
input [7:0] buff_din,
input buff_we,
output reg busy
);
assign sd_lba = lba;
trk_dpram buffer
(
.clock(clk),
.address_a(sd_buff_base + base_fix + sd_buff_addr),
.data_a(sd_buff_dout),
.wren_a(sd_ack & sd_buff_wr),
.q_a(sd_buff_din),
.address_b({sector, buff_addr}),
.data_b(buff_din),
.wren_b(buff_we),
.q_b(buff_dout)
);
wire [9:0] start_sectors[41] =
'{ 0, 0, 21, 42, 63, 84,105,126,147,168,189,210,231,252,273,294,315,336,357,376,395,
414,433,452,471,490,508,526,544,562,580,598,615,632,649,666,683,700,717,734,751};
reg [31:0] lba;
reg [12:0] base_fix;
reg [12:0] sd_buff_base;
always @(posedge clk) begin
reg old_ack;
reg [5:0] cur_track = 0;
reg old_change, ready = 0;
reg saving = 0;
old_change <= change;
if(~old_change & change) ready <= 1;
old_ack <= sd_ack;
if(sd_ack) {sd_rd,sd_wr} <= 0;
if(reset) begin
cur_track <= 'b111111;
busy <= 0;
sd_rd <= 0;
sd_wr <= 0;
saving<= 0;
end
else
if(busy) begin
if(old_ack && ~sd_ack) begin
if(sd_buff_base < 'h1800) begin
sd_buff_base <= sd_buff_base + 13'd512;
lba <= lba + 1'd1;
if(saving) sd_wr <= 1;
else sd_rd <= 1;
end
else
if(saving && (cur_track != track)) begin
saving <= 0;
cur_track <= track;
sd_buff_base <= 0;
base_fix <= start_sectors[track][0] ? 13'h1F00 : 13'h0000;
lba <= start_sectors[track][9:1];
sd_rd <= 1;
end
else
begin
busy <= 0;
end
end
end
else
if(ready) begin
if(save_track && cur_track != 'b111111) begin
saving <= 1;
sd_buff_base <= 0;
lba <= start_sectors[cur_track][9:1];
sd_wr <= 1;
busy <= 1;
end
else
if((cur_track != track) || (old_change && ~change)) begin
saving <= 0;
cur_track <= track;
sd_buff_base <= 0;
base_fix <= start_sectors[track][0] ? 13'h1F00 : 13'h0000;
lba <= start_sectors[track][9:1];
sd_rd <= 1;
busy <= 1;
end
end
end
endmodule
module trk_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=13)
(
input clock,
input [ADDRWIDTH-1:0] address_a,
input [DATAWIDTH-1:0] data_a,
input wren_a,
output reg [DATAWIDTH-1:0] q_a,
input [ADDRWIDTH-1:0] address_b,
input [DATAWIDTH-1:0] data_b,
input wren_b,
output reg [DATAWIDTH-1:0] q_b
);
logic [DATAWIDTH-1:0] ram[0:(1<<ADDRWIDTH)-1];
always_ff@(posedge clock) begin
if(wren_a) begin
ram[address_a] <= data_a;
q_a <= data_a;
end else begin
q_a <= ram[address_a];
end
end
always_ff@(posedge clock) begin
if(wren_b) begin
ram[address_b] <= data_b;
q_b <= data_b;
end else begin
q_b <= ram[address_b];
end
end
endmodule

View File

@@ -0,0 +1,675 @@
-------------------------------------------------------------------------------
--
-- (C) COPYRIGHT 2007-2017, Gideon's Logic Architectures
--
-------------------------------------------------------------------------------
-- Title : VIA 6522
-------------------------------------------------------------------------------
-- Author : Gideon Zweijtzer <gideon.zweijtzer@gmail.com>
-------------------------------------------------------------------------------
-- Description: This module implements the 6522 VIA chip.
-- Please note: A LOT OF REVERSE ENGINEERING has been done to
-- make this module as accurate as it is now. Please do not copy
-- (use in your own projects) without written permission of the
-- author.
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity c1541_via6522 is
port (
clock : in std_logic;
rising : in std_logic;
falling : in std_logic;
reset : in std_logic;
addr : in std_logic_vector(3 downto 0);
wen : in std_logic;
ren : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
phi2_ref : out std_logic;
-- pio --
port_a_o : out std_logic_vector(7 downto 0);
port_a_t_l : out std_logic_vector(7 downto 0);
port_a_i : in std_logic_vector(7 downto 0);
port_b_o : out std_logic_vector(7 downto 0);
port_b_t_l : out std_logic_vector(7 downto 0);
port_b_i : in std_logic_vector(7 downto 0);
-- handshake pins
ca1_i : in std_logic;
ca2_o : out std_logic;
ca2_i : in std_logic;
ca2_t_l : out std_logic;
cb1_o : out std_logic;
cb1_i : in std_logic;
cb1_t_l : out std_logic;
cb2_o : out std_logic;
cb2_i : in std_logic;
cb2_t_l : out std_logic;
irq_l : out std_logic );
end c1541_via6522;
architecture Gideon of c1541_via6522 is
type pio_t is
record
pra : std_logic_vector(7 downto 0);
ddra : std_logic_vector(7 downto 0);
prb : std_logic_vector(7 downto 0);
ddrb : std_logic_vector(7 downto 0);
end record;
constant pio_default : pio_t := (others => (others => '0'));
constant latch_reset_pattern : std_logic_vector(15 downto 0) := X"5550";
signal pio_i : pio_t;
signal port_a_c : std_logic_vector(7 downto 0) := (others => '0');
signal port_b_c : std_logic_vector(7 downto 0) := (others => '0');
signal irq_mask : std_logic_vector(6 downto 0) := (others => '0');
signal irq_flags : std_logic_vector(6 downto 0) := (others => '0');
signal irq_events : std_logic_vector(6 downto 0) := (others => '0');
signal irq_out : std_logic;
signal timer_a_latch : std_logic_vector(15 downto 0) := latch_reset_pattern;
signal timer_b_latch : std_logic_vector(15 downto 0) := latch_reset_pattern;
signal timer_a_count : std_logic_vector(15 downto 0) := latch_reset_pattern;
signal timer_b_count : std_logic_vector(15 downto 0) := latch_reset_pattern;
signal timer_a_out : std_logic;
signal timer_b_tick : std_logic;
signal acr, pcr : std_logic_vector(7 downto 0) := X"00";
signal shift_reg : std_logic_vector(7 downto 0) := X"00";
signal serport_en : std_logic;
signal ser_cb2_o : std_logic;
signal hs_cb2_o : std_logic;
signal trigger_serial: std_logic;
alias ca2_event : std_logic is irq_events(0);
alias ca1_event : std_logic is irq_events(1);
alias serial_event : std_logic is irq_events(2);
alias cb2_event : std_logic is irq_events(3);
alias cb1_event : std_logic is irq_events(4);
alias timer_b_event : std_logic is irq_events(5);
alias timer_a_event : std_logic is irq_events(6);
alias ca2_flag : std_logic is irq_flags(0);
alias ca1_flag : std_logic is irq_flags(1);
alias serial_flag : std_logic is irq_flags(2);
alias cb2_flag : std_logic is irq_flags(3);
alias cb1_flag : std_logic is irq_flags(4);
alias timer_b_flag : std_logic is irq_flags(5);
alias timer_a_flag : std_logic is irq_flags(6);
alias tmr_a_output_en : std_logic is acr(7);
alias tmr_a_freerun : std_logic is acr(6);
alias tmr_b_count_mode : std_logic is acr(5);
alias shift_dir : std_logic is acr(4);
alias shift_clk_sel : std_logic_vector(1 downto 0) is acr(3 downto 2);
alias shift_mode_control : std_logic_vector(2 downto 0) is acr(4 downto 2);
alias pb_latch_en : std_logic is acr(1);
alias pa_latch_en : std_logic is acr(0);
alias cb2_is_output : std_logic is pcr(7);
alias cb2_edge_select : std_logic is pcr(6); -- for when CB2 is input
alias cb2_no_irq_clr : std_logic is pcr(5); -- for when CB2 is input
alias cb2_out_mode : std_logic_vector(1 downto 0) is pcr(6 downto 5);
alias cb1_edge_select : std_logic is pcr(4);
alias ca2_is_output : std_logic is pcr(3);
alias ca2_edge_select : std_logic is pcr(2); -- for when CA2 is input
alias ca2_no_irq_clr : std_logic is pcr(1); -- for when CA2 is input
alias ca2_out_mode : std_logic_vector(1 downto 0) is pcr(2 downto 1);
alias ca1_edge_select : std_logic is pcr(0);
signal ira, irb : std_logic_vector(7 downto 0) := (others => '0');
signal write_t1c_h : std_logic;
signal write_t2c_h : std_logic;
signal ca1_c, ca2_c : std_logic;
signal cb1_c, cb2_c : std_logic;
signal ca1_d, ca2_d : std_logic;
signal cb1_d, cb2_d : std_logic;
signal ca2_handshake_o : std_logic;
signal ca2_pulse_o : std_logic;
signal cb2_handshake_o : std_logic;
signal cb2_pulse_o : std_logic;
signal shift_active : std_logic;
begin
irq_l <= not irq_out;
write_t1c_h <= '1' when addr = X"5" and wen='1' and falling = '1' else '0';
write_t2c_h <= '1' when addr = X"9" and wen='1' and falling = '1' else '0';
ca1_event <= (ca1_c xor ca1_d) and (ca1_d xor ca1_edge_select);
ca2_event <= (ca2_c xor ca2_d) and (ca2_d xor ca2_edge_select);
cb1_event <= (cb1_c xor cb1_d) and (cb1_d xor cb1_edge_select);
cb2_event <= (cb2_c xor cb2_d) and (cb2_d xor cb2_edge_select);
ca2_t_l <= not ca2_is_output;
cb2_t_l <= not cb2_is_output when serport_en='0' else shift_dir;
cb2_o <= hs_cb2_o when serport_en='0' else ser_cb2_o;
with ca2_out_mode select ca2_o <=
ca2_handshake_o when "00",
ca2_pulse_o when "01",
'0' when "10",
'1' when others;
with cb2_out_mode select hs_cb2_o <=
cb2_handshake_o when "00",
cb2_pulse_o when "01",
'0' when "10",
'1' when others;
process(irq_flags, irq_mask)
begin
if (irq_flags and irq_mask) = "0000000" then
irq_out <= '0';
else
irq_out <= '1';
end if;
end process;
process(clock)
begin
if rising_edge(clock) then
if rising = '1' then
phi2_ref <= '1';
elsif falling = '1' then
phi2_ref <= '0';
end if;
end if;
end process;
process(clock)
begin
if rising_edge(clock) then
-- CA1/CA2/CB1/CB2 edge detect flipflops
ca1_c <= To_X01(ca1_i);
ca2_c <= To_X01(ca2_i);
cb1_c <= To_X01(cb1_i);
cb2_c <= To_X01(cb2_i);
ca1_d <= ca1_c;
ca2_d <= ca2_c;
cb1_d <= cb1_c;
cb2_d <= cb2_c;
-- input registers
port_a_c <= port_a_i;
port_b_c <= port_b_i;
-- input latch emulation
if pa_latch_en = '0' or ca1_event = '1' then
ira <= port_a_c;
end if;
if pb_latch_en = '0' or cb1_event = '1' then
irb <= port_b_c;
end if;
-- CA2 logic
if ca1_event = '1' then
ca2_handshake_o <= '1';
elsif (ren = '1' or wen = '1') and addr = X"1" and falling = '1' then
ca2_handshake_o <= '0';
end if;
if falling = '1' then
if (ren = '1' or wen = '1') and addr = X"1" then
ca2_pulse_o <= '0';
else
ca2_pulse_o <= '1';
end if;
end if;
-- CB2 logic
if cb1_event = '1' then
cb2_handshake_o <= '1';
elsif (ren = '1' or wen = '1') and addr = X"0" and falling = '1' then
cb2_handshake_o <= '0';
end if;
if falling = '1' then
if (ren = '1' or wen = '1') and addr = X"0" then
cb2_pulse_o <= '0';
else
cb2_pulse_o <= '1';
end if;
end if;
-- Interrupt logic
irq_flags <= irq_flags or irq_events;
if falling = '1' then
trigger_serial <= '0';
end if;
-- Writes --
if wen='1' and falling = '1' then
case addr is
when X"0" => -- ORB
pio_i.prb <= data_in;
if cb2_no_irq_clr='0' then
cb2_flag <= '0';
end if;
cb1_flag <= '0';
when X"1" => -- ORA
pio_i.pra <= data_in;
if ca2_no_irq_clr='0' then
ca2_flag <= '0';
end if;
ca1_flag <= '0';
when X"2" => -- DDRB
pio_i.ddrb <= data_in;
when X"3" => -- DDRA
pio_i.ddra <= data_in;
when X"4" => -- TA LO counter (write=latch)
timer_a_latch(7 downto 0) <= data_in;
when X"5" => -- TA HI counter
timer_a_latch(15 downto 8) <= data_in;
timer_a_flag <= '0';
when X"6" => -- TA LO latch
timer_a_latch(7 downto 0) <= data_in;
when X"7" => -- TA HI latch
timer_a_latch(15 downto 8) <= data_in;
timer_a_flag <= '0';
when X"8" => -- TB LO latch
timer_b_latch(7 downto 0) <= data_in;
when X"9" => -- TB HI counter
timer_b_flag <= '0';
when X"A" => -- Serial port
serial_flag <= '0';
if shift_active = '0' then
trigger_serial <= '1';
end if;
when X"B" => -- ACR (Auxiliary Control Register)
acr <= data_in;
when X"C" => -- PCR (Peripheral Control Register)
pcr <= data_in;
when X"D" => -- IFR
irq_flags <= irq_flags and not data_in(6 downto 0);
when X"E" => -- IER
if data_in(7)='1' then -- set
irq_mask <= irq_mask or data_in(6 downto 0);
else -- clear
irq_mask <= irq_mask and not data_in(6 downto 0);
end if;
when X"F" => -- ORA no handshake
pio_i.pra <= data_in;
when others =>
null;
end case;
end if;
-- Reads - Output only --
data_out <= X"00";
case addr is
when X"0" => -- ORB
--Port B reads its own output register for pins set to output.
data_out <= (pio_i.prb and pio_i.ddrb) or (irb and not pio_i.ddrb);
when X"1" => -- ORA
data_out <= ira;
when X"2" => -- DDRB
data_out <= pio_i.ddrb;
when X"3" => -- DDRA
data_out <= pio_i.ddra;
when X"4" => -- TA LO counter
data_out <= timer_a_count(7 downto 0);
when X"5" => -- TA HI counter
data_out <= timer_a_count(15 downto 8);
when X"6" => -- TA LO latch
data_out <= timer_a_latch(7 downto 0);
when X"7" => -- TA HI latch
data_out <= timer_a_latch(15 downto 8);
when X"8" => -- TA LO counter
data_out <= timer_b_count(7 downto 0);
when X"9" => -- TA HI counter
data_out <= timer_b_count(15 downto 8);
when X"A" => -- SR
data_out <= shift_reg;
when X"B" => -- ACR
data_out <= acr;
when X"C" => -- PCR
data_out <= pcr;
when X"D" => -- IFR
data_out <= irq_out & irq_flags;
when X"E" => -- IER
data_out <= '0' & irq_mask;
when X"F" => -- ORA
data_out <= ira;
when others =>
null;
end case;
-- Read actions --
if ren = '1' and falling = '1' then
case addr is
when X"0" => -- ORB
if cb2_no_irq_clr='0' then
cb2_flag <= '0';
end if;
cb1_flag <= '0';
when X"1" => -- ORA
if ca2_no_irq_clr='0' then
ca2_flag <= '0';
end if;
ca1_flag <= '0';
when X"4" => -- TA LO counter
timer_a_flag <= '0';
when X"8" => -- TB LO counter
timer_b_flag <= '0';
when X"A" => -- SR
serial_flag <= '0';
trigger_serial <= '1';
when others =>
null;
end case;
end if;
if reset='1' then
pio_i <= pio_default;
irq_mask <= (others => '0');
irq_flags <= (others => '0');
acr <= (others => '0');
pcr <= (others => '0');
ca2_handshake_o <= '1';
ca2_pulse_o <= '1';
cb2_handshake_o <= '1';
cb2_pulse_o <= '1';
timer_a_latch <= latch_reset_pattern;
timer_b_latch <= latch_reset_pattern;
trigger_serial <= '0';
end if;
end if;
end process;
-- PIO Out select --
port_a_o <= pio_i.pra;
port_b_o(6 downto 0) <= pio_i.prb(6 downto 0);
port_b_o(7) <= pio_i.prb(7) when tmr_a_output_en='0' else timer_a_out;
port_a_t_l <= not pio_i.ddra;
port_b_t_l(6 downto 0) <= not pio_i.ddrb(6 downto 0);
port_b_t_l(7) <= not (pio_i.ddrb(7) or tmr_a_output_en);
-- Timer A
tmr_a: block
signal timer_a_reload : std_logic;
signal timer_a_oneshot_trig : std_logic;
signal timer_a_toggle : std_logic;
begin
process(clock)
begin
if rising_edge(clock) then
if falling = '1' then
-- always count, or load
if timer_a_reload = '1' then
timer_a_count <= timer_a_latch;
timer_a_reload <= '0';
timer_a_oneshot_trig <= '0';
else
if timer_a_count = X"0000" then
-- generate an event if we were triggered
timer_a_reload <= '1';
end if;
--Timer coutinues to count in both free run and one shot.
timer_a_count <= timer_a_count - X"0001";
end if;
end if;
if rising = '1' then
if timer_a_event = '1' then
timer_a_toggle <= not timer_a_toggle;
end if;
end if;
if write_t1c_h = '1' then
timer_a_toggle <= '0';
timer_a_count <= data_in & timer_a_latch(7 downto 0);
timer_a_reload <= '0';
timer_a_oneshot_trig <= '1';
end if;
if reset='1' then
timer_a_toggle <= '1';
timer_a_count <= latch_reset_pattern;
timer_a_reload <= '0';
timer_a_oneshot_trig <= '0';
end if;
end if;
end process;
timer_a_out <= timer_a_toggle;
timer_a_event <= rising and timer_a_reload and (tmr_a_freerun or timer_a_oneshot_trig);
end block tmr_a;
-- Timer B
tmr_b: block
signal timer_b_reload_lo : std_logic;
signal timer_b_oneshot_trig : std_logic;
signal timer_b_timeout : std_logic;
signal pb6_c, pb6_d : std_logic;
begin
process(clock)
variable timer_b_decrement : std_logic;
begin
if rising_edge(clock) then
timer_b_decrement := '0';
if rising = '1' then
pb6_c <= To_X01(port_b_i(6));
pb6_d <= pb6_c;
end if;
if falling = '1' then
timer_b_timeout <= '0';
timer_b_tick <= '0';
if tmr_b_count_mode = '1' then
if (pb6_d='1' and pb6_c='0') then
timer_b_decrement := '1';
end if;
else -- one shot or used for shift register
timer_b_decrement := '1';
end if;
if timer_b_decrement = '1' then
if timer_b_count = X"0000" then
if timer_b_oneshot_trig = '1' then
timer_b_oneshot_trig <= '0';
timer_b_timeout <= '1';
end if;
end if;
if timer_b_count(7 downto 0) = X"00" then
case shift_mode_control is
when "001" | "101" | "100" =>
timer_b_reload_lo <= '1';
timer_b_tick <= '1';
when others =>
null;
end case;
end if;
timer_b_count <= timer_b_count - X"0001";
end if;
if timer_b_reload_lo = '1' then
timer_b_count(7 downto 0) <= timer_b_latch(7 downto 0);
timer_b_reload_lo <= '0';
end if;
end if;
if write_t2c_h = '1' then
timer_b_count <= data_in & timer_b_latch(7 downto 0);
timer_b_oneshot_trig <= '1';
end if;
if reset='1' then
timer_b_count <= latch_reset_pattern;
timer_b_reload_lo <= '0';
timer_b_oneshot_trig <= '0';
end if;
end if;
end process;
timer_b_event <= rising and timer_b_timeout;
end block tmr_b;
ser: block
signal shift_clock_d : std_logic;
signal shift_clock : std_logic;
signal shift_tick_r : std_logic;
signal shift_tick_f : std_logic;
signal cb2_c : std_logic := '0';
signal bit_cnt : integer range 0 to 7;
signal shift_pulse : std_logic;
begin
process(shift_active, timer_b_tick, shift_clk_sel, shift_clock, shift_clock_d)
begin
case shift_clk_sel is
when "10" =>
shift_pulse <= '1';
when "00"|"01" =>
shift_pulse <= timer_b_tick;
when others =>
shift_pulse <= shift_clock and not shift_clock_d;
end case;
if shift_active = '0' then
shift_pulse <= '0';
end if;
end process;
process(clock)
begin
if rising_edge(clock) then
if rising = '1' then
cb2_c <= To_X01(cb2_i);
if shift_active='0' then
shift_clock <= '1';
elsif shift_clk_sel = "11" then
shift_clock <= To_X01(cb1_i);
elsif shift_pulse = '1' then
shift_clock <= not shift_clock;
end if;
shift_clock_d <= shift_clock;
if shift_tick_f = '1' then
ser_cb2_o <= shift_reg(7);
end if;
end if;
if reset = '1' then
shift_clock <= '1';
shift_clock_d <= '1';
ser_cb2_o <= '1';
end if;
end if;
end process;
cb1_t_l <= '1' when shift_clk_sel="11" else not serport_en;
cb1_o <= shift_clock_d;
serport_en <= shift_dir or shift_clk_sel(1) or shift_clk_sel(0);
process(clock)
begin
if rising_edge(clock) then
if reset = '1' then
shift_reg <= X"FF";
shift_tick_r <= '0';
shift_tick_f <= '0';
elsif falling = '1' then
shift_tick_r <= not shift_clock_d and shift_clock;
shift_tick_f <= shift_clock_d and not shift_clock;
if wen = '1' and addr = X"A" then
shift_reg <= data_in;
elsif shift_tick_r = '1' then
if shift_dir='1' then -- output
shift_reg <= shift_reg(6 downto 0) & shift_reg(7);
else
shift_reg <= shift_reg(6 downto 0) & cb2_c;
end if;
end if;
end if;
end if;
end process;
-- tell people that we're ready!
serial_event <= shift_tick_r and not shift_active and rising;
process(clock)
begin
if rising_edge(clock) then
if falling = '1' then
if shift_active = '0' then
if trigger_serial = '1' then
bit_cnt <= 7;
shift_active <= '1';
end if;
else -- we're active
if shift_clk_sel = "00" then
shift_active <= shift_dir; -- when '1' we're active, but for mode 000 we go inactive.
elsif shift_pulse = '1' and shift_clock = '1' then
if bit_cnt = 0 then
shift_active <= '0';
else
bit_cnt <= bit_cnt - 1;
end if;
end if;
end if;
end if;
if reset='1' then
shift_active <= '0';
bit_cnt <= 0;
end if;
end if;
end process;
end block ser;
end Gideon;

View File

@@ -0,0 +1,137 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity alu is
generic (
support_bcd : boolean := true );
port (
operation : in std_logic_vector(2 downto 0);
enable : in std_logic;
n_in : in std_logic;
v_in : in std_logic;
z_in : in std_logic;
c_in : in std_logic;
d_in : in std_logic;
data_a : in std_logic_vector(7 downto 0);
data_b : in std_logic_vector(7 downto 0);
n_out : out std_logic;
v_out : out std_logic;
z_out : out std_logic;
c_out : out std_logic;
data_out : out std_logic_vector(7 downto 0));
end alu;
architecture gideon of alu is
signal data_out_i : std_logic_vector(7 downto 0) := X"FF";
signal zero : std_logic;
signal sum_c : std_logic;
signal sum_n : std_logic;
signal sum_z : std_logic;
signal sum_v : std_logic;
signal sum_result : std_logic_vector(7 downto 0) := X"FF";
signal oper4 : std_logic_vector(3 downto 0);
begin
-- ORA $nn AND $nn EOR $nn ADC $nn STA $nn LDA $nn CMP $nn SBC $nn
with oper4 select data_out_i <=
data_a or data_b when "1000",
data_a and data_b when "1001",
data_a xor data_b when "1010",
sum_result when "1011" | "1110" | "1111",
data_b when others;
zero <= '1' when data_out_i = X"00" else '0';
sum: process(data_a, data_b, c_in, operation, d_in)
variable b : std_logic_vector(7 downto 0);
variable sum_l : std_logic_vector(4 downto 0);
variable sum_h : std_logic_vector(4 downto 0);
begin
-- for subtraction invert second operand
if operation(2)='1' then -- invert b
b := not data_b;
else
b := data_b;
end if;
-- sum_l(4) = carry of lower end, carry in is masked to '1' for CMP
sum_l := ('0' & data_a(3 downto 0)) + ('0' & b(3 downto 0)) + (c_in or not operation(0));
sum_h := ('0' & data_a(7 downto 4)) + ('0' & b(7 downto 4)) + sum_l(4);
if sum_l(3 downto 0)="0000" and sum_h(3 downto 0)="0000" then
sum_z <= '1';
else
sum_z <= '0';
end if;
sum_n <= sum_h(3);
sum_c <= sum_h(4);
sum_v <= (sum_h(3) xor data_a(7)) and (sum_h(3) xor data_b(7) xor operation(2));
-- fix up in decimal mode (not for CMP!)
if d_in='1' and support_bcd then
if operation(2)='0' then -- ADC
sum_h := ('0' & data_a(7 downto 4)) + ('0' & b(7 downto 4));
if sum_l(4) = '1' or sum_l(3 downto 2)="11" or sum_l(3 downto 1)="101" then -- >9 (10-11, 12-15)
sum_l := sum_l + ('0' & X"6");
sum_l(4) := '1';
end if;
-- negative when sum_h + sum_l(4) = 8
sum_h := sum_h + sum_l(4);
sum_n <= sum_h(3);
if sum_h(4) = '1' or sum_h(3 downto 2)="11" or sum_h(3 downto 1)="101" then --
sum_h := sum_h + 6;
sum_c <= '1';
end if;
-- carry and overflow are output after fix
-- sum_c <= sum_h(4);
-- sum_v <= (sum_h(3) xor data_a(7)) and (sum_h(3) xor data_b(7) xor operation(2));
elsif operation(0)='1' then -- SBC
-- flags are not adjusted in subtract mode
if sum_l(4) = '0' then
sum_l := sum_l - 6;
end if;
if sum_h(4) = '0' then
sum_h := sum_h - 6;
end if;
end if;
end if;
sum_result <= sum_h(3 downto 0) & sum_l(3 downto 0);
end process;
oper4 <= enable & operation;
with oper4 select c_out <=
sum_c when "1011" | "1111" | "1110",
c_in when others;
with oper4 select z_out <=
sum_z when "1011" | "1111" | "1110",
zero when "1000" | "1001" | "1010" | "1101",
z_in when others;
with oper4 select n_out <=
sum_n when "1011" | "1111",
data_out_i(7) when "1000" | "1001" | "1010" | "1101" | "1110",
n_in when others;
with oper4 select v_out <=
sum_v when "1011" | "1111",
v_in when others;
data_out <= data_out_i;
end gideon;

View File

@@ -0,0 +1,66 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity bit_cpx_cpy is
port (
operation : in std_logic_vector(2 downto 0);
enable : in std_logic := '1'; -- instruction(1 downto 0)="00"
n_in : in std_logic;
v_in : in std_logic;
z_in : in std_logic;
c_in : in std_logic;
data_in : in std_logic_vector(7 downto 0);
a_reg : in std_logic_vector(7 downto 0);
x_reg : in std_logic_vector(7 downto 0);
y_reg : in std_logic_vector(7 downto 0);
n_out : out std_logic;
v_out : out std_logic;
z_out : out std_logic;
c_out : out std_logic );
end bit_cpx_cpy;
architecture gideon of bit_cpx_cpy is
signal reg : std_logic_vector(7 downto 0) := (others => '0');
signal diff : std_logic_vector(8 downto 0) := (others => '0');
signal zero_cmp : std_logic;
signal zero_ld : std_logic;
signal zero_bit : std_logic;
signal oper4 : std_logic_vector(3 downto 0);
begin
-- *** BIT *** *** STY LDY CPY CPX
reg <= x_reg when operation(0)='1' else y_reg;
diff <= ('1' & reg) - ('0' & data_in);
zero_cmp <= '1' when diff(7 downto 0)=X"00" else '0';
zero_ld <= '1' when data_in=X"00" else '0';
zero_bit <= '1' when (data_in and a_reg)=X"00" else '0';
oper4 <= enable & operation;
with oper4 select c_out <=
diff(8) when "1110" | "1111", -- CPX / CPY
c_in when others;
with oper4 select z_out <=
zero_cmp when "1110" | "1111", -- CPX / CPY
zero_ld when "1101",
zero_bit when "1001",
z_in when others;
with oper4 select n_out <=
diff(7) when "1110" | "1111", -- CPX / CPY
data_in(7) when "1101" | "1001", -- LDY / BIT
n_in when others;
with oper4 select v_out <=
data_in(6) when "1001", -- BIT
v_in when others;
end gideon;

View File

@@ -0,0 +1,193 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library work;
use work.pkg_6502_decode.all;
-- this module puts the alu, shifter and bit/compare unit together
entity data_oper is
generic (
support_bcd : boolean := true );
port (
inst : in std_logic_vector(7 downto 0);
n_in : in std_logic;
v_in : in std_logic;
z_in : in std_logic;
c_in : in std_logic;
d_in : in std_logic;
i_in : in std_logic;
data_in : in std_logic_vector(7 downto 0);
a_reg : in std_logic_vector(7 downto 0);
x_reg : in std_logic_vector(7 downto 0);
y_reg : in std_logic_vector(7 downto 0);
s_reg : in std_logic_vector(7 downto 0);
alu_out : out std_logic_vector(7 downto 0);
mem_out : out std_logic_vector(7 downto 0);
impl_out : out std_logic_vector(7 downto 0);
set_a : out std_logic;
set_x : out std_logic;
set_y : out std_logic;
set_s : out std_logic;
n_out : out std_logic;
v_out : out std_logic;
z_out : out std_logic;
c_out : out std_logic;
d_out : out std_logic;
i_out : out std_logic );
end data_oper;
architecture gideon of data_oper is
signal shift_sel : std_logic_vector(1 downto 0) := "00";
signal shift_din : std_logic_vector(7 downto 0) := X"00";
signal shift_dout: std_logic_vector(7 downto 0) := X"00";
signal alu_data_a: std_logic_vector(7 downto 0) := X"00";
signal row0_n : std_logic;
signal row0_v : std_logic;
signal row0_z : std_logic;
signal row0_c : std_logic;
signal shft_n : std_logic;
signal shft_z : std_logic;
signal shft_c : std_logic;
signal alu_n : std_logic;
signal alu_v : std_logic;
signal alu_z : std_logic;
signal alu_c : std_logic;
signal impl_n : std_logic;
signal impl_z : std_logic;
signal impl_c : std_logic;
signal impl_v : std_logic;
signal impl_i : std_logic;
signal impl_d : std_logic;
signal shift_en : std_logic;
signal alu_en : std_logic;
signal impl_en : std_logic;
signal impl_flags: boolean;
begin
shift_sel <= shifter_in_select(inst);
with shift_sel select shift_din <=
data_in when "01",
a_reg when "10",
data_in and a_reg when "11",
X"FF" when others;
shift_en <= '1' when is_shift(inst) else '0';
alu_en <= '1' when is_alu(inst) else '0';
row0: entity work.bit_cpx_cpy
port map (
operation => inst(7 downto 5),
enable => '1',
n_in => n_in,
v_in => v_in,
z_in => z_in,
c_in => c_in,
data_in => data_in,
a_reg => a_reg,
x_reg => x_reg,
y_reg => y_reg,
n_out => row0_n,
v_out => row0_v,
z_out => row0_z,
c_out => row0_c );
shft: entity work.shifter
port map (
operation => inst(7 downto 5),
enable => shift_en,
c_in => c_in,
n_in => n_in,
z_in => z_in,
data_in => shift_din,
c_out => shft_c,
n_out => shft_n,
z_out => shft_z,
data_out => shift_dout );
alu_data_a <= a_reg and x_reg when x_to_alu(inst) else a_reg;
alu1: entity work.alu
generic map (
support_bcd => support_bcd )
port map (
operation => inst(7 downto 5),
enable => alu_en,
n_in => shft_n,
v_in => v_in,
z_in => shft_z,
c_in => shft_c,
d_in => d_in,
data_a => alu_data_a,
data_b => shift_dout,
n_out => alu_n,
v_out => alu_v,
z_out => alu_z,
c_out => alu_c,
data_out => alu_out );
mem_out <= shift_dout;
impl_en <= '1' when is_implied(inst) else '0';
impl_flags <= is_implied(inst) and (inst(4)='1' or inst(7)='1');
impl: entity work.implied
port map (
inst => inst,
enable => impl_en,
c_in => c_in,
i_in => i_in,
n_in => n_in,
z_in => z_in,
d_in => d_in,
v_in => v_in,
reg_a => a_reg,
reg_x => x_reg,
reg_y => y_reg,
reg_s => s_reg,
i_out => impl_i,
d_out => impl_d,
c_out => impl_c,
n_out => impl_n,
z_out => impl_z,
v_out => impl_v,
set_a => set_a,
set_x => set_x,
set_y => set_y,
set_s => set_s,
data_out => impl_out );
n_out <= impl_n when impl_flags else row0_n when inst(1 downto 0)="00" else alu_n;
v_out <= impl_v when impl_flags else row0_v when inst(1 downto 0)="00" else alu_v;
z_out <= impl_z when impl_flags else row0_z when inst(1 downto 0)="00" else alu_z;
c_out <= impl_c when impl_flags else row0_c when inst(1 downto 0)="00" else alu_c;
i_out <= impl_i when impl_flags else i_in;
d_out <= impl_d when impl_flags else d_in;
end gideon;

View File

@@ -0,0 +1,114 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity implied is
port (
inst : in std_logic_vector(7 downto 0);
enable : in std_logic;
c_in : in std_logic;
i_in : in std_logic;
n_in : in std_logic;
z_in : in std_logic;
d_in : in std_logic;
v_in : in std_logic;
reg_a : in std_logic_vector(7 downto 0);
reg_x : in std_logic_vector(7 downto 0);
reg_y : in std_logic_vector(7 downto 0);
reg_s : in std_logic_vector(7 downto 0);
c_out : out std_logic;
i_out : out std_logic;
n_out : out std_logic;
z_out : out std_logic;
d_out : out std_logic;
v_out : out std_logic;
set_a : out std_logic;
set_x : out std_logic;
set_y : out std_logic;
set_s : out std_logic;
data_out : out std_logic_vector(7 downto 0));
end implied;
architecture gideon of implied is
type t_int4_array is array(natural range <>) of integer range 0 to 3;
-- ROMS for the upper (negative) implied instructions
constant reg_sel_rom : t_int4_array(0 to 15) := ( 2,0,2,1,1,0,1,1,2,0,2,1,1,3,1,1 ); -- 0=A, 1=X, 2=Y, 3=S
constant decr_rom : std_logic_vector(0 to 15) := "1000001000000000";
constant incr_rom : std_logic_vector(0 to 15) := "0011000000000000";
constant nz_flags : std_logic_vector(0 to 15) := "1111111010000100";
constant v_flag : std_logic_vector(0 to 15) := "0000000001000000";
constant d_flag : std_logic_vector(0 to 15) := "0000000000110000";
constant set_a_rom : std_logic_vector(0 to 15) := "0000100010000000";
constant set_x_rom : std_logic_vector(0 to 15) := "0001011000000100";
constant set_y_rom : std_logic_vector(0 to 15) := "1110000000000000";
constant set_s_rom : std_logic_vector(0 to 15) := "0000000000001000";
-- ROMS for the lower (positive) implied instructions
constant shft_rom : std_logic_vector(0 to 15) := "0000111100000000";
constant c_flag : std_logic_vector(0 to 15) := "0000000011000000";
constant i_flag : std_logic_vector(0 to 15) := "0000000000110000";
signal selected_reg : std_logic_vector(7 downto 0) := X"00";
signal operation : integer range 0 to 15;
signal reg_sel : integer range 0 to 3;
signal result : std_logic_vector(7 downto 0) := X"00";
signal add : std_logic_vector(7 downto 0) := X"00";
signal carry : std_logic := '0';
signal zero : std_logic := '0';
signal n_hi : std_logic;
signal z_hi : std_logic;
signal v_hi : std_logic;
signal d_hi : std_logic;
signal n_lo : std_logic;
signal z_lo : std_logic;
signal c_lo : std_logic;
signal i_lo : std_logic;
begin
operation <= conv_integer(inst(4) & inst(1) & inst(6 downto 5));
reg_sel <= reg_sel_rom(operation);
with reg_sel select selected_reg <=
reg_a when 0,
reg_x when 1,
reg_y when 2,
reg_s when others;
add <= (others => decr_rom(operation));
carry <= incr_rom(operation);
result <= selected_reg + add + carry;
zero <= '1' when result = X"00" else '0';
data_out <= result;
n_hi <= result(7) when nz_flags(operation)='1' else n_in;
z_hi <= zero when nz_flags(operation)='1' else z_in;
v_hi <= '0' when v_flag(operation)='1' else v_in;
d_hi <= inst(5) when d_flag(operation)='1' else d_in;
-- in high, C and I are never set
c_lo <= inst(5) when c_flag(operation)='1' else c_in;
i_lo <= inst(5) when i_flag(operation)='1' else i_in;
-- in low, V, N, Z and D are never set
set_a <= set_a_rom(operation) and inst(7) and enable;
set_x <= set_x_rom(operation) and inst(7) and enable;
set_y <= set_y_rom(operation) and inst(7) and enable;
set_s <= set_s_rom(operation) and inst(7) and enable;
c_out <= c_in when inst(7)='1' else c_lo; -- C can only be set in lo
i_out <= i_in when inst(7)='1' else i_lo; -- I can only be set in lo
v_out <= v_hi when inst(7)='1' else v_in; -- V can only be set in hi
d_out <= d_hi when inst(7)='1' else d_in; -- D can only be set in hi
n_out <= n_hi when inst(7)='1' else n_in; -- N can only be set in hi
z_out <= z_hi when inst(7)='1' else z_in; -- Z can only be set in hi
end gideon;

View File

@@ -0,0 +1,248 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
package pkg_6502_decode is
function is_absolute(inst: std_logic_vector(7 downto 0)) return boolean;
function is_abs_jump(inst: std_logic_vector(7 downto 0)) return boolean;
function is_immediate(inst: std_logic_vector(7 downto 0)) return boolean;
function is_implied(inst: std_logic_vector(7 downto 0)) return boolean;
function is_stack(inst: std_logic_vector(7 downto 0)) return boolean;
function is_push(inst: std_logic_vector(7 downto 0)) return boolean;
function is_zeropage(inst: std_logic_vector(7 downto 0)) return boolean;
function is_indirect(inst: std_logic_vector(7 downto 0)) return boolean;
function is_relative(inst: std_logic_vector(7 downto 0)) return boolean;
function is_load(inst: std_logic_vector(7 downto 0)) return boolean;
function is_store(inst: std_logic_vector(7 downto 0)) return boolean;
function is_shift(inst: std_logic_vector(7 downto 0)) return boolean;
function is_alu(inst: std_logic_vector(7 downto 0)) return boolean;
function is_rmw(inst: std_logic_vector(7 downto 0)) return boolean;
function is_jump(inst: std_logic_vector(7 downto 0)) return boolean;
function is_postindexed(inst: std_logic_vector(7 downto 0)) return boolean;
function is_illegal(inst: std_logic_vector(7 downto 0)) return boolean;
function stack_idx(inst: std_logic_vector(7 downto 0)) return std_logic_vector;
constant c_stack_idx_brk : std_logic_vector(1 downto 0) := "00";
constant c_stack_idx_jsr : std_logic_vector(1 downto 0) := "01";
constant c_stack_idx_rti : std_logic_vector(1 downto 0) := "10";
constant c_stack_idx_rts : std_logic_vector(1 downto 0) := "11";
function select_index_y (inst: std_logic_vector(7 downto 0)) return boolean;
function store_a_from_alu (inst: std_logic_vector(7 downto 0)) return boolean;
function load_a (inst: std_logic_vector(7 downto 0)) return boolean;
function load_x (inst: std_logic_vector(7 downto 0)) return boolean;
function load_y (inst: std_logic_vector(7 downto 0)) return boolean;
function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector;
function x_to_alu (inst: std_logic_vector(7 downto 0)) return boolean;
end;
package body pkg_6502_decode is
function is_absolute(inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 4320 = X11X | 1101
if inst(3 downto 2)="11" then
return true;
elsif inst(4 downto 2)="110" and inst(0)='1' then
return true;
end if;
return false;
end function;
function is_jump(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return inst(7 downto 6)="01" and inst(3 downto 0)=X"C";
end function;
function is_immediate(inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 76543210 = 1XX000X0
if inst(7)='1' and inst(4 downto 2)="000" and inst(0)='0' then
return true;
-- 76543210 = XXX010X1
elsif inst(4 downto 2)="010" and inst(0)='1' then
return true;
end if;
return false;
end function;
function is_implied(inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 4320 = X100
return inst(3 downto 2)="10" and inst(0)='0';
end function;
function is_stack(inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 76543210
-- 0xx0x000
return inst(7)='0' and inst(4)='0' and inst(2 downto 0)="000";
end function;
function is_push(inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- we already know it's a stack operation, so only the direction is important
return inst(5)='0';
end function;
function is_zeropage(inst: std_logic_vector(7 downto 0)) return boolean is
begin
if inst(3 downto 2)="01" then
return true;
elsif inst(3 downto 2)="00" and inst(0)='1' then
return true;
end if;
return false;
end function;
function is_indirect(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return (inst(3 downto 2)="00" and inst(0)='1');
end function;
function is_relative(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return (inst(4 downto 0)="10000");
end function;
function is_store(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return (inst(7 downto 5)="100");
end function;
function is_shift(inst: std_logic_vector(7 downto 0)) return boolean is
begin
if inst(7)='1' and inst(4 downto 2)="010" then
return false;
end if;
return (inst(1)='1');
end function;
function is_alu(inst: std_logic_vector(7 downto 0)) return boolean is
begin
if inst(7)='0' and inst(4 downto 1)="0101" then
return false;
end if;
return (inst(0)='1');
end function;
function is_load(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return not is_store(inst) and not is_rmw(inst);
end function;
function is_rmw(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return inst(1)='1' and inst(7 downto 6)/="10";
end function;
function is_abs_jump(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return is_jump(inst) and inst(5)='0';
end function;
function is_postindexed(inst: std_logic_vector(7 downto 0)) return boolean is
begin
return inst(4)='1';
end function;
function stack_idx(inst: std_logic_vector(7 downto 0)) return std_logic_vector is
begin
return inst(6 downto 5);
end function;
function select_index_y (inst: std_logic_vector(7 downto 0)) return boolean is
begin
if inst(4)='1' and inst(2)='0' and inst(0)='1' then -- XXX1X0X1
return true;
elsif inst(7 downto 6)="10" and inst(2 downto 1)="11" then -- 10XXX11X
return true;
end if;
return false;
end function;
-- function flags_bit_group (inst: std_logic_vector(7 downto 0)) return boolean is
-- begin
-- return inst(2 downto 0)="100";
-- end function;
--
-- function flags_alu_group (inst: std_logic_vector(7 downto 0)) return boolean is
-- begin
-- return inst(1 downto 0)="01"; -- could also choose not to look at bit 1 (overlap)
-- end function;
--
-- function flags_shift_group (inst: std_logic_vector(7 downto 0)) return boolean is
-- begin
-- return inst(1 downto 0)="10"; -- could also choose not to look at bit 0 (overlap)
-- end function;
function load_a (inst: std_logic_vector(7 downto 0)) return boolean is
begin
return (inst = X"68");
end function;
function store_a_from_alu (inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 0XXXXXX1 or alu operations "lo"
-- 1X100001 or alu operations "hi" (except store and cmp)
-- 0XX01010 (implied)
return (inst(7)='0' and inst(4 downto 0)="01010") or
(inst(7)='0' and inst(0)='1') or
(inst(7)='1' and inst(0)='1' and inst(5)='1');
end function;
function load_x (inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 101XXX1X or 1100101- (for SAX #)
if inst(7 downto 1)="1100101" then
return true;
end if;
return inst(7 downto 5)="101" and inst(1)='1' and not is_implied(inst);
end function;
function load_y (inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 101XXX00
return inst(7 downto 5)="101" and inst(1 downto 0)="00" and not is_implied(inst);
end function;
function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector is
begin
-- 00 = none, 01 = memory, 10 = A, 11 = A & M
if inst(4 downto 2)="010" and inst(7)='0' then
return inst(1 downto 0);
end if;
return "01";
end function;
-- function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector is
-- begin
-- -- 0=memory, 1=A
-- if inst(4 downto 1)="0101" and inst(7)='0' then
-- return "01";
-- end if;
-- return "10";
-- end function;
function is_illegal (inst: std_logic_vector(7 downto 0)) return boolean is
type t_my16bit_array is array(natural range <>) of std_logic_vector(15 downto 0);
constant c_illegal_map : t_my16bit_array(0 to 15) := (
X"989C", X"9C9C", X"888C", X"9C9C", X"889C", X"9C9C", X"889C", X"9C9C",
X"8A8D", X"D88C", X"8888", X"888C", X"888C", X"9C9C", X"888C", X"9C9C" );
variable row : std_logic_vector(15 downto 0);
begin
row := c_illegal_map(conv_integer(inst(7 downto 4)));
return (row(conv_integer(inst(3 downto 0))) = '1');
end function;
function x_to_alu (inst: std_logic_vector(7 downto 0)) return boolean is
begin
-- 1-00101- 8A,8B,CA,CB
return inst(5 downto 1)="00101" and inst(7)='1';
end function;
end;

View File

@@ -0,0 +1,18 @@
library ieee;
use ieee.std_logic_1164.all;
package pkg_6502_defs is
subtype t_amux is integer range 0 to 3;
constant c_amux_vector : t_amux := 0;
constant c_amux_addr : t_amux := 1;
constant c_amux_stack : t_amux := 2;
constant c_amux_pc : t_amux := 3;
type t_pc_oper is (keep, increment, copy, from_alu);
type t_adl_oper is (keep, increment, add_idx, load_bus, copy_dreg);
type t_adh_oper is (keep, increment, clear, load_bus);
type t_sp_oper is (keep, increment, decrement);
type t_dout_mux is (reg_d, reg_accu, reg_axy, reg_flags, reg_pcl, reg_pch, shift_res);
end;

View File

@@ -0,0 +1,88 @@
package pkg_6502_opcodes is
type t_opcode_array is array(0 to 255) of string(1 to 13);
constant opcode_array : t_opcode_array := (
"BRK ", "ORA ($nn,X) ", "HLT* ", "ASO*($nn,X) ",
"BOT*$nn ", "ORA $nn ", "ASL $nn ", "ASO*$nn ",
"PHP ", "ORA # ", "ASL A ", "ORA*# ",
"BOT*$nnnnn ", "ORA $nnnn ", "ASL $nnnn ", "ASO*$nnnn ",
"BPL rel ", "ORA ($nn),Y ", "HLT* ", "ASO*($nn),Y ",
"BOT*$nn,X ", "ORA $nn,X ", "ASL $nn,X ", "ASO*$nn,X ",
"CLC ", "ORA $nnnn,Y ", "NOP* ", "ASO*$nnnn,Y ",
"BOT*$nnnn,X ", "ORA $nnnn,X ", "ASL $nnnn,X ", "ASO*$nnnn,X ",
"JSR $nnnn ", "AND ($nn,X) ", "HLT* ", "RLA*($nn,X) ",
"BIT $nn ", "AND $nn ", "ROL $nn ", "RLA*$nn ",
"PLP ", "AND # ", "ROL A ", "AND*# ",
"BIT $nnnn ", "AND $nnnn ", "ROL $nnnn ", "RLA*$nnnn ",
"BMI rel ", "AND ($nn),Y ", "HLT* ", "RLA*($nn),Y ",
"BIT*$nn,X ", "AND $nn,X ", "ROL $nn,X ", "RLA*$nn,X ",
"SEC ", "AND $nnnn,Y ", "NOP* ", "RLA*$nnnn,Y ",
"BIT*$nnnn,X ", "AND $nnnn,X ", "ROL $nnnn,X ", "RLA*$nnnn,X ",
"RTI ", "EOR ($nn,X) ", "HLT* ", "LSE*($nn,X) ",
"RDM* ", "EOR $nn ", "LSR $nn ", "LSE*$nn ",
"PHA ", "EOR # ", "LSR A ", "EOR*# ",
"JMP $nnnn ", "EOR $nnnn ", "LSR $nnnn ", "LSE*$nnnn ",
"BVC rel ", "EOR ($nn),Y ", "HLT* ", "LSE*($nn),Y ",
"RDM* ", "EOR $nn,X ", "LSR $nn,X ", "LSE*$nn,X ",
"CLI ", "EOR $nnnn,Y ", "NOP* ", "LSE*$nnnn,Y ",
"JMP*$nnnn ", "EOR $nnnn,X ", "LSR $nnnn,X ", "LSE*$nnnn,X ",
"RTS ", "ADC ($nn,X) ", "HLT* ", "RRA*($nn,X) ",
"RDM* ", "ADC $nn ", "ROR $nn ", "RRA*$nn ",
"PLA ", "ADC # ", "ROR A ", "ADC*# ",
"JMP ($nnnn) ", "ADC $nnnn ", "ROR $nnnn ", "RRA*$nnnn ",
"BVS rel ", "ADC ($nn),Y ", "HLT* ", "RRA*($nn),Y ",
"RDM* ", "ADC $nn,X ", "ROR $nn,X ", "RRA*$nn,X ",
"SEI ", "ADC $nnnn,Y ", "NOP* ", "RRA*$nnnn,Y ",
"JMP*($nnnn,X)", "ADC $nnnn,X ", "ROR $nnnn,X ", "RRA*$nnnn,X ",
"SKB* ", "STA ($nn,X) ", "SKB* ", "AXS*($nn,X) ",
"STY $nn ", "STA $nn ", "STX $nn ", "AXS*$nn ",
"DEY ", "SKB* ", "TXA ", "???* ",
"STY $nnnn ", "STA $nnnn ", "STX $nnnn ", "AXS*$nnnn ",
"BCC ", "STA ($nn),Y ", "HLT* ", "AXS*($nn),Y ",
"STY $nn,X ", "STA $nn,X ", "STX $nn,Y ", "AXS*$nn,Y ",
"TYA ", "STA $nnnn,Y ", "TXS ", "AXS*$nnnn,Y ",
"STY*$nnnn,X ", "STA $nnnn,X ", "STX*$nnnn,Y ", "AXS*$nnnn,Y ",
"LDY # ", "LDA ($nn,X) ", "LDX # ", "LAX*($nn,X) ",
"LDY $nn ", "LDA $nn ", "LDX $nn ", "LAX*$nn ",
"TAY ", "LDA # ", "TAX ", "LAX*# ",
"LDY $nnnn ", "LDA $nnnn ", "LDX $nnnn ", "LAX*$nnnn ",
"BCS ", "LDA ($nn),Y ", "HLT* ", "LAX*($nn),Y ",
"LDY $nn,X ", "LDA $nn,X ", "LDX $nn,Y ", "LAX*$nn,Y ",
"CLV ", "LDA $nnnn,Y ", "TSX ", "LAX*$nnnn,Y ",
"LDY $nnnn,X ", "LDA $nnnn,X ", "LDX $nnnn,Y ", "LAX*$nnnn,Y ",
"CPY # ", "CMP ($nn,X) ", "SKB* ", "DCM*($nn,X) ",
"CPY $nn ", "CMP $nn ", "DEC $nn ", "DCM*$nn ",
"INY ", "CMP # ", "DEX ", "SAX*# (used!)",
"CPY $nnnn ", "CMP $nnnn ", "DEC $nnnn ", "DCM*$nnnn ",
"BNE ", "CMP ($nn),Y ", "HLT* ", "DCM*($nn),Y ",
"RDM* ", "CMP $nn,X ", "DEC $nn,X ", "DCM*$nn,X ",
"CLD ", "CMP $nnnn,Y ", "NOP* ", "DCM*$nnnn,Y ",
"RDM*$nnnn,X ", "CMP $nnnn,X ", "DEC $nnnn,X ", "DCM*$nnnn,X ",
"CPX # ", "SBC ($nn,X) ", "SKB* ", "INS*($nn,X) ",
"CPX $nn ", "SBC $nn ", "INC $nn ", "INS*$nn ",
"INX ", "SBC # ", "NOP ", "SBC*# ",
"CPX $nnnn ", "SBC $nnnn ", "INC $nnnn ", "INS*$nnnn ",
"BEQ ", "SBC ($nn),Y ", "HLT* ", "INS*($nn),Y ",
"RDM* ", "SBC $nn,X ", "INC $nn,X ", "INS*$nn,X ",
"SED ", "SBC $nnnn,Y ", "NOP* ", "INS*$nnnn,Y ",
"RDM*$nnnn,X ", "SBC $nnnn,X ", "INC $nnnn,X ", "INS*$nnnn,X " );
end;

View File

@@ -0,0 +1,472 @@
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.pkg_6502_defs.all;
use work.pkg_6502_decode.all;
entity proc_control is
port (
clock : in std_logic;
clock_en : in std_logic;
reset : in std_logic;
interrupt : in std_logic;
i_reg : in std_logic_vector(7 downto 0);
index_carry : in std_logic;
pc_carry : in std_logic;
branch_taken : in boolean;
sync : out std_logic;
dummy_cycle : out std_logic;
set_b : out std_logic;
latch_dreg : out std_logic;
copy_d2p : out std_logic;
reg_update : out std_logic;
rwn : out std_logic;
vect_bit : out std_logic := '0';
a16 : out std_logic;
a_mux : out t_amux := c_amux_pc;
dout_mux : out t_dout_mux;
pc_oper : out t_pc_oper;
s_oper : out t_sp_oper;
adl_oper : out t_adl_oper;
adh_oper : out t_adh_oper );
end proc_control;
architecture gideon of proc_control is
type t_state is (fetch, decode, absolute, abs_hi, abs_fix, branch, branch_fix,
indir1, indir2, jump_sub, jump, retrn, rmw1, rmw2, vector, startup,
zp, zp_idx, zp_indir, push1, push2, push3, pull1, pull2, pull3 );
signal state : t_state;
signal next_state : t_state;
signal next_cp_p : std_logic;
signal next_rwn : std_logic;
signal next_dreg : std_logic;
signal next_amux : t_amux;
signal next_dout : t_dout_mux;
signal next_set_b : std_logic;
signal next_dummy : std_logic;
signal vectoring : std_logic;
begin
-- combinatroial process
process(state, i_reg, index_carry, pc_carry, branch_taken, interrupt, vectoring)
variable v_stack_idx : std_logic_vector(1 downto 0);
begin
-- defaults
sync <= '0';
pc_oper <= increment;
next_amux <= c_amux_pc;
next_rwn <= '1';
next_state <= state;
adl_oper <= keep;
adh_oper <= keep;
s_oper <= keep;
next_dreg <= '1';
next_cp_p <= '0';
next_dout <= reg_d;
next_set_b <= '0';
next_dummy <= '0';
v_stack_idx := stack_idx(i_reg);
case state is
when fetch =>
sync <= '1';
if interrupt='1' then
pc_oper <= keep;
next_rwn <= '0';
next_dout <= reg_pch;
next_state <= push1;
next_amux <= c_amux_stack;
else
next_state <= decode;
next_set_b <= '1';
end if;
when decode =>
adl_oper <= load_bus;
adh_oper <= clear;
if is_absolute(i_reg) then
if is_abs_jump(i_reg) then
next_state <= jump;
else
next_state <= absolute;
end if;
elsif is_implied(i_reg) then
pc_oper <= keep;
if is_stack(i_reg) then -- PHP, PLP, PHA, PLA
next_amux <= c_amux_stack;
case v_stack_idx is
when "00" => -- PHP
next_state <= push3;
next_rwn <= '0';
next_dout <= reg_flags;
when "10" => -- PHA
next_state <= push3;
next_rwn <= '0';
next_dout <= reg_accu;
when others =>
next_state <= pull1;
end case;
else
next_state <= fetch;
end if;
elsif is_zeropage(i_reg) then
next_amux <= c_amux_addr;
if is_indirect(i_reg) then
if is_postindexed(i_reg) then
next_state <= zp_indir;
else
next_state <= zp;
next_dummy <= '1';
end if;
else
next_state <= zp;
if is_store(i_reg) and not is_postindexed(i_reg) then
next_rwn <= '0';
next_dout <= reg_axy;
end if;
end if;
elsif is_relative(i_reg) then
next_state <= branch;
elsif is_stack(i_reg) then -- non-implied stack operations like BRK, JSR, RTI and RTS
next_amux <= c_amux_stack;
case v_stack_idx is
when c_stack_idx_brk =>
-- next_set_b <= '1';
next_rwn <= '0';
next_dout <= reg_pch;
next_state <= push1;
when c_stack_idx_jsr =>
next_dreg <= '0';
next_dout <= reg_pch;
next_state <= jump_sub;
when c_stack_idx_rti =>
next_state <= pull1;
when c_stack_idx_rts =>
next_state <= pull2;
when others =>
null;
end case;
elsif is_immediate(i_reg) then
next_state <= fetch;
end if;
when absolute =>
next_state <= abs_hi;
next_amux <= c_amux_addr;
adh_oper <= load_bus;
if is_postindexed(i_reg) then
adl_oper <= add_idx;
elsif not is_zeropage(i_reg) then
if is_store(i_reg) then
next_rwn <='0';
next_dout <= reg_axy;
end if;
end if;
if is_zeropage(i_reg) then
pc_oper <= keep;
else
pc_oper <= increment;
end if;
when abs_hi =>
pc_oper <= keep;
if is_postindexed(i_reg) then
if is_load(i_reg) and index_carry='0' then
next_amux <= c_amux_pc;
next_state <= fetch;
else
next_amux <= c_amux_addr;
next_state <= abs_fix;
if index_carry='1' then
adh_oper <= increment;
end if;
end if;
if is_store(i_reg) then
next_rwn <= '0';
next_dout <= reg_axy;
end if;
else -- not post-indexed
if is_jump(i_reg) then
next_amux <= c_amux_addr;
next_state <= jump;
adl_oper <= increment;
elsif is_rmw(i_reg) then
next_rwn <= '0';
next_dout <= reg_d;
next_dummy <= '1';
next_state <= rmw1;
next_amux <= c_amux_addr;
else
next_state <= fetch;
next_amux <= c_amux_pc;
end if;
end if;
when abs_fix =>
pc_oper <= keep;
if is_rmw(i_reg) then
next_state <= rmw1;
next_amux <= c_amux_addr;
next_rwn <= '0';
next_dout <= reg_d;
next_dummy <= '1';
else
next_state <= fetch;
next_amux <= c_amux_pc;
end if;
when branch =>
next_amux <= c_amux_pc;
if branch_taken then
pc_oper <= from_alu; -- add offset
next_state <= branch_fix;
else
pc_oper <= increment;
next_state <= decode;
sync <= '1';
end if;
when branch_fix =>
next_amux <= c_amux_pc;
if pc_carry='1' then
next_state <= fetch;
pc_oper <= keep; -- this will fix the PCH, since the carry is set
else
sync <= '1';
next_state <= decode;
pc_oper <= increment;
end if;
when indir1 =>
pc_oper <= keep;
next_state <= indir2;
next_amux <= c_amux_addr;
adl_oper <= copy_dreg;
adh_oper <= load_bus;
if is_store(i_reg) then
next_rwn <= '0';
next_dout <= reg_axy;
end if;
when indir2 =>
pc_oper <= keep;
if is_rmw(i_reg) then
next_dummy <= '1';
next_rwn <= '0';
next_dout <= reg_d;
next_state <= rmw1;
next_amux <= c_amux_addr;
else
next_state <= fetch;
next_amux <= c_amux_pc;
end if;
when jump_sub =>
next_state <= push1;
pc_oper <= keep;
next_dout <= reg_pch;
next_rwn <= '0';
next_dreg <= '0';
next_amux <= c_amux_stack;
when jump =>
pc_oper <= copy;
next_amux <= c_amux_pc;
if is_stack(i_reg) and v_stack_idx=c_stack_idx_rts and vectoring='0' then
next_state <= retrn;
else
next_state <= fetch;
end if;
when retrn =>
pc_oper <= increment;
next_state <= fetch;
when pull1 =>
s_oper <= increment;
next_state <= pull2;
next_amux <= c_amux_stack;
pc_oper <= keep;
when pull2 =>
pc_oper <= keep;
if is_implied(i_reg) then
next_state <= fetch;
next_amux <= c_amux_pc;
next_cp_p <= not v_stack_idx(1); -- only for PLP
else -- it was a stack operation, but not implied (RTS/RTI)
s_oper <= increment;
next_state <= pull3;
next_amux <= c_amux_stack;
next_cp_p <= not v_stack_idx(0); -- only for RTI
end if;
when pull3 =>
pc_oper <= keep;
s_oper <= increment;
next_state <= jump;
next_amux <= c_amux_stack;
when push1 =>
pc_oper <= keep;
s_oper <= decrement;
next_state <= push2;
next_amux <= c_amux_stack;
next_rwn <= '0';
next_dreg <= '0';
next_dout <= reg_pcl;
when push2 =>
pc_oper <= keep;
s_oper <= decrement;
if (v_stack_idx=c_stack_idx_jsr) and vectoring='0' then
next_state <= jump;
next_amux <= c_amux_pc;
else
next_state <= push3;
next_rwn <= '0';
next_dout <= reg_flags;
next_amux <= c_amux_stack;
end if;
when push3 =>
pc_oper <= keep;
s_oper <= decrement;
if is_implied(i_reg) and vectoring='0' then -- PHP, PHA
next_amux <= c_amux_pc;
next_state <= fetch;
else
next_state <= vector;
next_amux <= c_amux_vector;
end if;
when rmw1 =>
pc_oper <= keep;
next_state <= rmw2;
next_amux <= c_amux_addr;
next_rwn <= '0';
next_dout <= shift_res;
when rmw2 =>
pc_oper <= keep;
next_state <= fetch;
next_amux <= c_amux_pc;
when vector =>
next_state <= jump;
pc_oper <= keep;
next_amux <= c_amux_vector;
when startup =>
next_state <= vector;
pc_oper <= keep;
next_amux <= c_amux_vector;
when zp =>
pc_oper <= keep;
if is_postindexed(i_reg) or is_indirect(i_reg) then
adl_oper <= add_idx;
next_state <= zp_idx;
next_amux <= c_amux_addr;
if is_postindexed(i_reg) and is_store(i_reg) then
next_rwn <= '0';
next_dout <= reg_axy;
end if;
elsif is_rmw(i_reg) then
next_dummy <= '1';
next_state <= rmw1;
next_amux <= c_amux_addr;
next_rwn <= '0';
next_dout <= reg_d;
else
next_state <= fetch;
next_amux <= c_amux_pc;
end if;
when zp_idx =>
pc_oper <= keep;
if is_indirect(i_reg) then
next_state <= indir1;
adl_oper <= increment;
next_amux <= c_amux_addr;
elsif is_rmw(i_reg) then
next_state <= rmw1;
next_amux <= c_amux_addr;
next_rwn <= '0';
next_dout <= reg_d;
else
next_state <= fetch;
next_amux <= c_amux_pc;
end if;
when zp_indir =>
pc_oper <= keep;
next_state <= absolute;
next_amux <= c_amux_addr;
adl_oper <= increment;
when others =>
null;
end case;
end process;
reg_update <= '1' when (state = fetch) and vectoring='0' and
not is_stack(i_reg) and not is_relative(i_reg) else '0';
vect_bit <= '0' when state = vector else '1';
process(clock)
begin
if rising_edge(clock) then
if clock_en='1' then
state <= next_state;
a_mux <= next_amux;
dout_mux <= next_dout;
rwn <= next_rwn;
latch_dreg <= next_dreg and next_rwn; -- disable dreg latch for writes
copy_d2p <= next_cp_p;
set_b <= next_set_b;
dummy_cycle <= next_dummy;
if next_amux = c_amux_vector or next_amux = c_amux_pc then
a16 <= '1';
else
a16 <= '0';
end if;
if state = fetch then
vectoring <= interrupt;
end if;
end if;
if reset='1' then
a16 <= '1';
state <= startup; --vector;
a_mux <= c_amux_vector;
rwn <= '1';
latch_dreg <= '1';
dout_mux <= reg_d;
copy_d2p <= '0';
set_b <= '0';
vectoring <= '0';
dummy_cycle <= '0';
end if;
end if;
end process;
end gideon;

View File

@@ -0,0 +1,233 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library work;
use work.pkg_6502_defs.all;
entity proc_core is
generic (
vector_page : std_logic_vector(15 downto 4) := X"FFF";
support_bcd : boolean := true );
port(
clock : in std_logic;
clock_en : in std_logic;
reset : in std_logic;
irq_n : in std_logic := '1';
nmi_n : in std_logic := '1';
so_n : in std_logic := '1';
sync_out : out std_logic;
pc_out : out std_logic_vector(15 downto 0);
inst_out : out std_logic_vector(7 downto 0);
addr_out : out std_logic_vector(16 downto 0);
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
read_write_n : out std_logic );
end proc_core;
architecture structural of proc_core is
signal index_carry : std_logic;
signal pc_carry : std_logic;
signal branch_taken : boolean;
signal i_reg : std_logic_vector(7 downto 0);
signal d_reg : std_logic_vector(7 downto 0);
signal a_reg : std_logic_vector(7 downto 0);
signal x_reg : std_logic_vector(7 downto 0);
signal y_reg : std_logic_vector(7 downto 0);
signal s_reg : std_logic_vector(7 downto 0);
signal p_reg : std_logic_vector(7 downto 0);
signal latch_dreg : std_logic;
signal reg_update : std_logic;
signal copy_d2p : std_logic;
signal sync : std_logic;
signal rwn : std_logic;
signal vect_bit : std_logic;
signal a_mux : t_amux;
signal pc_oper : t_pc_oper;
signal s_oper : t_sp_oper;
signal adl_oper : t_adl_oper;
signal adh_oper : t_adh_oper;
signal dout_mux : t_dout_mux;
signal alu_out : std_logic_vector(7 downto 0);
signal mem_out : std_logic_vector(7 downto 0);
signal impl_out : std_logic_vector(7 downto 0);
signal set_a : std_logic;
signal set_x : std_logic;
signal set_y : std_logic;
signal set_s : std_logic;
signal vect_addr : std_logic_vector(3 downto 0);
signal interrupt : std_logic;
signal new_flags : std_logic_vector(7 downto 0);
signal n_out : std_logic;
signal v_out : std_logic;
signal c_out : std_logic;
signal z_out : std_logic;
signal d_out : std_logic;
signal i_out : std_logic;
signal set_b : std_logic;
signal clear_b : std_logic;
signal a16 : std_logic;
begin
inst_out <= i_reg; -- for debug only
new_flags(7) <= n_out;
new_flags(6) <= v_out;
new_flags(5) <= '1';
new_flags(4) <= p_reg(4);
new_flags(3) <= d_out;
new_flags(2) <= i_out;
new_flags(1) <= z_out;
new_flags(0) <= c_out;
ctrl: entity work.proc_control
port map (
clock => clock,
clock_en => clock_en,
reset => reset,
interrupt => interrupt,
i_reg => i_reg,
index_carry => index_carry,
pc_carry => pc_carry,
branch_taken => branch_taken,
sync => sync,
latch_dreg => latch_dreg,
reg_update => reg_update,
set_b => set_b,
copy_d2p => copy_d2p,
vect_bit => vect_bit,
a16 => a16,
rwn => rwn,
a_mux => a_mux,
dout_mux => dout_mux,
pc_oper => pc_oper,
s_oper => s_oper,
adl_oper => adl_oper,
adh_oper => adh_oper );
oper: entity work.data_oper
generic map (
support_bcd => support_bcd )
port map (
inst => i_reg,
n_in => p_reg(7),
v_in => p_reg(6),
z_in => p_reg(1),
c_in => p_reg(0),
d_in => p_reg(3),
i_in => p_reg(2),
data_in => d_reg,
a_reg => a_reg,
x_reg => x_reg,
y_reg => y_reg,
s_reg => s_reg,
alu_out => alu_out,
mem_out => mem_out,
impl_out => impl_out,
set_a => set_a,
set_x => set_x,
set_y => set_y,
set_s => set_s,
n_out => n_out,
v_out => v_out,
z_out => z_out,
c_out => c_out,
d_out => d_out,
i_out => i_out );
regs: entity work.proc_registers
generic map (
vector_page => vector_page )
port map (
clock => clock,
clock_en => clock_en,
reset => reset,
-- package pins
data_in => data_in,
data_out => data_out,
so_n => so_n,
-- data from "data_oper"
alu_data => alu_out,
mem_data => mem_out,
new_flags => new_flags,
-- from implied handler
set_a => set_a,
set_x => set_x,
set_y => set_y,
set_s => set_s,
set_data => impl_out,
-- from interrupt controller
vect_addr => vect_addr,
interrupt => interrupt,
set_b => set_b,
clear_b => clear_b,
-- from processor state machine and decoder
sync => sync,
latch_dreg => latch_dreg,
vect_bit => vect_bit,
reg_update => reg_update,
copy_d2p => copy_d2p,
a_mux => a_mux,
dout_mux => dout_mux,
pc_oper => pc_oper,
s_oper => s_oper,
adl_oper => adl_oper,
adh_oper => adh_oper,
-- outputs to processor state machine
i_reg => i_reg,
index_carry => index_carry,
pc_carry => pc_carry,
branch_taken => branch_taken,
-- register outputs
addr_out => addr_out(15 downto 0),
d_reg => d_reg,
a_reg => a_reg,
x_reg => x_reg,
y_reg => y_reg,
s_reg => s_reg,
p_reg => p_reg,
pc_out => pc_out );
intr: entity work.proc_interrupt
port map (
clock => clock,
clock_en => clock_en,
reset => reset,
irq_n => irq_n,
nmi_n => nmi_n,
i_flag => p_reg(2),
clear_b => clear_b,
vect_bit => vect_bit,
interrupt => interrupt,
vect_addr => vect_addr );
read_write_n <= rwn;
addr_out(16) <= a16;
sync_out <= sync;
end structural;

View File

@@ -0,0 +1,83 @@
library ieee;
use ieee.std_logic_1164.all;
entity proc_interrupt is
port (
clock : in std_logic;
clock_en : in std_logic;
reset : in std_logic;
irq_n : in std_logic;
nmi_n : in std_logic;
i_flag : in std_logic;
clear_b : out std_logic;
vect_bit : in std_logic;
interrupt : out std_logic;
vect_addr : out std_logic_vector(3 downto 0) );
end proc_interrupt;
architecture gideon of proc_interrupt is
signal irq_c : std_logic := '0';
signal nmi_c : std_logic := '0';
signal nmi_d : std_logic := '0';
signal nmi_act : std_logic := '0';
signal vect_h : std_logic_vector(1 downto 0) := "00";
type state_t is (idle, do_irq, do_nmi);
signal state : state_t;
begin
vect_addr <= '1' & vect_h & vect_bit;
interrupt <= irq_c or nmi_act;
process(clock)
begin
if rising_edge(clock) then
irq_c <= not (irq_n or i_flag);
nmi_c <= not nmi_n;
clear_b <= '0';
if clock_en='1' then
nmi_d <= nmi_c;
if nmi_d = '0' and nmi_c = '1' then -- edge
nmi_act <= '1';
end if;
case state is
when idle =>
vect_h <= "11"; -- FE/FF
if nmi_act = '1' then
vect_h <= "01"; -- FA/FB
state <= do_nmi;
elsif irq_c = '1' then
state <= do_irq;
clear_b <= '1';
end if;
when do_irq =>
if vect_bit='0' or irq_c='0' then
state <= idle;
end if;
when do_nmi =>
if vect_bit='0' then
nmi_act <= '0';
state <= idle;
end if;
when others =>
state <= idle;
end case;
end if;
if reset='1' then
vect_h <= "10"; -- FC/FD 1100
state <= do_nmi;
nmi_act <= '0';
end if;
end if;
end process;
end gideon;

View File

@@ -0,0 +1,303 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library work;
use work.pkg_6502_defs.all;
use work.pkg_6502_decode.all;
entity proc_registers is
generic (
vector_page : std_logic_vector(15 downto 4) := X"FFF" );
port (
clock : in std_logic;
clock_en : in std_logic;
reset : in std_logic;
-- package pins
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
so_n : in std_logic := '1';
-- data from "data_oper"
alu_data : in std_logic_vector(7 downto 0);
mem_data : in std_logic_vector(7 downto 0);
new_flags : in std_logic_vector(7 downto 0);
-- from implied handler
set_a : in std_logic;
set_x : in std_logic;
set_y : in std_logic;
set_s : in std_logic;
set_data : in std_logic_vector(7 downto 0);
-- interrupt pins
interrupt : in std_logic;
vect_addr : in std_logic_vector(3 downto 0);
set_b : in std_logic;
clear_b : in std_logic;
-- from processor state machine and decoder
sync : in std_logic; -- latch ireg
latch_dreg : in std_logic;
vect_bit : in std_logic;
reg_update : in std_logic;
copy_d2p : in std_logic;
a_mux : in t_amux;
dout_mux : in t_dout_mux;
pc_oper : in t_pc_oper;
s_oper : in t_sp_oper;
adl_oper : in t_adl_oper;
adh_oper : in t_adh_oper;
-- outputs to processor state machine
i_reg : out std_logic_vector(7 downto 0) := X"00";
index_carry : out std_logic;
pc_carry : out std_logic;
branch_taken : out boolean;
-- register outputs
addr_out : out std_logic_vector(15 downto 0) := X"FFFF";
d_reg : out std_logic_vector(7 downto 0) := X"00";
a_reg : out std_logic_vector(7 downto 0) := X"00";
x_reg : out std_logic_vector(7 downto 0) := X"00";
y_reg : out std_logic_vector(7 downto 0) := X"00";
s_reg : out std_logic_vector(7 downto 0) := X"00";
p_reg : out std_logic_vector(7 downto 0) := X"00";
pc_out : out std_logic_vector(15 downto 0) );
end proc_registers;
architecture gideon of proc_registers is
-- signal a_reg : std_logic_vector(7 downto 0);
signal dreg : std_logic_vector(7 downto 0) := X"00";
signal a_reg_i : std_logic_vector(7 downto 0) := X"00";
signal x_reg_i : std_logic_vector(7 downto 0) := X"00";
signal y_reg_i : std_logic_vector(7 downto 0) := X"00";
signal selected_idx : std_logic_vector(7 downto 0) := X"00";
signal i_reg_i : std_logic_vector(7 downto 0) := X"00";
signal s_reg_i : std_logic_vector(7 downto 0) := X"00";
signal p_reg_i : std_logic_vector(7 downto 0) := X"30";
signal pcl, pch : std_logic_vector(7 downto 0) := X"FF";
signal adl, adh : std_logic_vector(7 downto 0) := X"00";
signal pc_carry_i : std_logic;
signal pc_carry_d : std_logic;
signal branch_flag : std_logic;
signal reg_out : std_logic_vector(7 downto 0);
signal vect : std_logic_vector(3 downto 0) := "1111";
signal dreg_zero : std_logic;
alias C_flag : std_logic is p_reg_i(0);
alias Z_flag : std_logic is p_reg_i(1);
alias I_flag : std_logic is p_reg_i(2);
alias D_flag : std_logic is p_reg_i(3);
alias B_flag : std_logic is p_reg_i(4);
alias V_flag : std_logic is p_reg_i(6);
alias N_flag : std_logic is p_reg_i(7);
begin
dreg_zero <= '1' when dreg=X"00" else '0';
process(clock)
variable pcl_t : std_logic_vector(8 downto 0);
variable adl_t : std_logic_vector(8 downto 0);
begin
if rising_edge(clock) then
if clock_en='1' then
-- Data Register
if latch_dreg='1' then
dreg <= data_in;
end if;
-- Flags Register
if copy_d2p = '1' then
p_reg_i <= dreg;
elsif reg_update='1' then
p_reg_i <= new_flags;
end if;
if vect_bit='0' then
I_flag <= '1';
end if;
if set_b='1' then
B_flag <= '1';
elsif clear_b='1' then
B_flag <= '0';
end if;
if so_n='0' then -- only 1 bit is affected, so no syncronization needed
V_flag <= '1';
end if;
-- Instruction Register
if sync='1' then
i_reg_i <= data_in;
-- Fix for PLA only :(
if load_a(i_reg_i) then
a_reg_i <= dreg;
N_flag <= dreg(7);
Z_flag <= dreg_zero;
end if;
end if;
-- Logic for the Program Counter
pc_carry_i <= '0';
case pc_oper is
when increment =>
if pcl = X"FF" then
pch <= pch + 1;
end if;
pcl <= pcl + 1;
when copy =>
pcl <= dreg;
pch <= data_in;
when from_alu =>
pcl_t := ('0' & pcl) + (dreg(7) & dreg); -- sign extended 1 bit
pcl <= pcl_t(7 downto 0);
pc_carry_i <= pcl_t(8);
pc_carry_d <= dreg(7);
when others => -- keep (and fix)
if pc_carry_i='1' then
if pc_carry_d='1' then
pch <= pch - 1;
else
pch <= pch + 1;
end if;
end if;
end case;
-- Logic for the Address register
case adl_oper is
when increment =>
adl <= adl + 1;
when add_idx =>
adl_t := ('0' & dreg) + ('0' & selected_idx);
adl <= adl_t(7 downto 0);
index_carry <= adl_t(8);
when load_bus =>
adl <= data_in;
when copy_dreg =>
adl <= dreg;
when others =>
null;
end case;
case adh_oper is
when increment =>
adh <= adh + 1;
when clear =>
adh <= (others => '0');
when load_bus =>
adh <= data_in;
when others =>
null;
end case;
-- Logic for ALU register
if reg_update='1' then
if set_a='1' then
a_reg_i <= set_data;
elsif store_a_from_alu(i_reg_i) then
a_reg_i <= alu_data;
end if;
end if;
-- Logic for Index registers
if reg_update='1' then
if set_x='1' then
x_reg_i <= set_data;
elsif load_x(i_reg_i) then
x_reg_i <= alu_data; --dreg; -- alu is okay, too (they should be the same)
end if;
end if;
if reg_update='1' then
if set_y='1' then
y_reg_i <= set_data;
elsif load_y(i_reg_i) then
y_reg_i <= dreg;
end if;
end if;
-- Logic for the Stack Pointer
if set_s='1' then
s_reg_i <= set_data;
else
case s_oper is
when increment =>
s_reg_i <= s_reg_i + 1;
when decrement =>
s_reg_i <= s_reg_i - 1;
when others =>
null;
end case;
end if;
end if;
-- Reset
if reset='1' then
p_reg_i <= X"34"; -- I=1
index_carry <= '0';
end if;
end if;
end process;
with i_reg_i(7 downto 6) select branch_flag <=
N_flag when "00",
V_flag when "01",
C_flag when "10",
Z_flag when "11",
'0' when others;
branch_taken <= (branch_flag xor not i_reg_i(5))='1';
with a_mux select addr_out <=
vector_page & vect_addr when 0,
adh & adl when 1,
X"01" & s_reg_i when 2,
pch & pcl when 3;
with i_reg_i(1 downto 0) select reg_out <=
y_reg_i when "00",
a_reg_i when "01",
x_reg_i when "10",
a_reg_i and x_reg_i when others;
with dout_mux select data_out <=
dreg when reg_d,
a_reg_i when reg_accu,
reg_out when reg_axy,
p_reg_i or X"20" when reg_flags,
pcl when reg_pcl,
pch when reg_pch,
mem_data when shift_res,
X"FF" when others;
selected_idx <= y_reg_i when select_index_y(i_reg_i) else x_reg_i;
pc_carry <= pc_carry_i;
s_reg <= s_reg_i;
p_reg <= p_reg_i;
i_reg <= i_reg_i;
a_reg <= a_reg_i;
x_reg <= x_reg_i;
y_reg <= y_reg_i;
d_reg <= dreg;
pc_out <= pch & pcl;
end gideon;

View File

@@ -0,0 +1,60 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity shifter is
port (
operation : in std_logic_vector(2 downto 0);
enable : in std_logic := '1'; -- instruction(1)
c_in : in std_logic;
n_in : in std_logic;
z_in : in std_logic;
data_in : in std_logic_vector(7 downto 0);
c_out : out std_logic;
n_out : out std_logic;
z_out : out std_logic;
data_out : out std_logic_vector(7 downto 0) := X"00");
end shifter;
architecture gideon of shifter is
signal data_out_i : std_logic_vector(7 downto 0) := X"00";
signal zero : std_logic := '0';
signal oper4 : std_logic_vector(3 downto 0) := X"0";
begin
-- ASL $nn ROL $nn LSR $nn ROR $nn STX $nn LDX $nn DEC $nn INC $nn
with operation select data_out_i <=
data_in(6 downto 0) & '0' when "000",
data_in(6 downto 0) & c_in when "001",
'0' & data_in(7 downto 1) when "010",
c_in & data_in(7 downto 1) when "011",
data_in - 1 when "110",
data_in + 1 when "111",
data_in when others;
zero <= '1' when data_out_i = X"00" else '0';
oper4 <= enable & operation;
with oper4 select c_out <=
data_in(7) when "1000" | "1001",
data_in(0) when "1010" | "1011",
c_in when others;
with oper4 select z_out <=
zero when "1000" | "1001" | "1010" | "1011" | "1101" | "1110" | "1111",
z_in when others;
with oper4 select n_out <=
data_out_i(7) when "1000" | "1001" | "1010" | "1011" | "1101" | "1110" | "1111",
n_in when others;
data_out <= data_out_i when enable='1' else data_in;
end gideon;

View File

@@ -0,0 +1,316 @@
---------------------------------------------------------------------------------
-- Commodore 1541 gcr floppy (read/write) by Dar (darfpga@aol.fr) 23-May-2017
-- http://darfpga.blogspot.fr
--
-- produces GCR data, byte(ready) and sync signal to feed c1541_logic from current
-- track buffer ram which contains D64 data
--
-- gets GCR data from c1541_logic, while producing byte(ready) signal. Data feed
-- track buffer ram after conversion
--
-- Input clk 32MHz
--
---------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity gcr_floppy is
port(
clk32 : in std_logic;
dout : out std_logic_vector(7 downto 0); -- data from ram to 1541 logic
din : in std_logic_vector(7 downto 0); -- data from 1541 logic to ram
mode : in std_logic; -- read/write
mtr : in std_logic; -- stepper motor on/off
sync_n : out std_logic; -- reading SYNC bytes
byte_n : out std_logic; -- byte ready
track : in std_logic_vector(5 downto 0);
sector : out std_logic_vector(4 downto 0);
byte_addr : out std_logic_vector(7 downto 0);
ram_do : in std_logic_vector(7 downto 0);
ram_di : buffer std_logic_vector(7 downto 0);
ram_we : out std_logic;
ram_ready : in std_logic
);
end gcr_floppy;
architecture struct of gcr_floppy is
signal bit_clk_en : std_logic;
signal sync_cnt : std_logic_vector(5 downto 0) := (others => '0');
signal byte_cnt : std_logic_vector(8 downto 0) := (others => '0');
signal nibble : std_logic := '0';
signal gcr_bit_cnt : std_logic_vector(3 downto 0) := (others => '0');
signal bit_cnt : std_logic_vector(2 downto 0) := (others => '0');
signal sync_in_n : std_logic;
signal byte_in_n : std_logic;
signal sector_dbl : std_logic_vector(4 downto 0) := (others => '0');
signal state : std_logic := '0';
signal data_header : std_logic_vector(7 downto 0);
signal data_body : std_logic_vector(7 downto 0);
signal data : std_logic_vector(7 downto 0);
signal data_cks : std_logic_vector(7 downto 0);
signal gcr_nibble : std_logic_vector(4 downto 0);
signal gcr_bit : std_logic;
signal gcr_byte : std_logic_vector(7 downto 0);
signal mode_r1 : std_logic;
signal mode_r2 : std_logic;
type gcr_array is array(0 to 15) of std_logic_vector(4 downto 0);
signal gcr_lut : gcr_array :=
("01010","11010","01001","11001",
"01110","11110","01101","11101",
"10010","10011","01011","11011",
"10110","10111","01111","10101");
signal sector_max : std_logic_vector(4 downto 0);
signal gcr_byte_out : std_logic_vector(7 downto 0);
signal gcr_bit_out : std_logic;
signal gcr_nibble_out : std_logic_vector(4 downto 0);
signal nibble_out : std_logic_vector(3 downto 0);
signal autorise_write : std_logic;
signal autorise_count : std_logic;
begin
sync_n <= sync_in_n when mtr = '1' and ram_ready = '1' else '1';
sector <= sector_dbl;
with byte_cnt select
data_header <=
X"08" when "000000000",
"00"&track xor "000"&sector_dbl when "000000001",
"000"&sector_dbl when "000000010",
"00"&track when "000000011",
X"20" when "000000100",
X"20" when "000000101",
X"0F" when others;
with byte_cnt select
data_body <=
X"07" when "000000000",
data_cks when "100000001",
X"00" when "100000010",
X"00" when "100000011",
X"0F" when "100000100",
X"0F" when "100000101",
X"0F" when "100000110",
X"0F" when "100000111",
X"0F" when "100001000",
X"0F" when "100001001",
X"0F" when "100001010",
X"0F" when "100001011",
X"0F" when "100001100",
X"0F" when "100001101",
X"0F" when "100001110",
X"0F" when "100001111",
X"0F" when "100010000",
X"0F" when "100010001",
ram_do when others;
with state select
data <= data_header when '0', data_body when others;
with nibble select
gcr_nibble <=
gcr_lut(to_integer(unsigned(data(7 downto 4)))) when '0',
gcr_lut(to_integer(unsigned(data(3 downto 0)))) when others;
gcr_bit <= gcr_nibble(to_integer(unsigned(gcr_bit_cnt)));
sector_max <= "10100" when track < std_logic_vector(to_unsigned(18,6)) else
"10010" when track < std_logic_vector(to_unsigned(25,6)) else
"10001" when track < std_logic_vector(to_unsigned(31,6)) else
"10000" ;
gcr_bit_out <= gcr_byte_out(to_integer(unsigned(not bit_cnt)));
with gcr_nibble_out select
nibble_out <= X"0" when "01010",--"01010",
X"1" when "01011",--"11010",
X"2" when "10010",--"01001",
X"3" when "10011",--"11001",
X"4" when "01110",--"01110",
X"5" when "01111",--"11110",
X"6" when "10110",--"01101",
X"7" when "10111",--"11101",
X"8" when "01001",--"10010",
X"9" when "11001",--"10011",
X"A" when "11010",--"01011",
X"B" when "11011",--"11011",
X"C" when "01101",--"10110",
X"D" when "11101",--"10111",
X"E" when "11110",--"01111",
X"F" when others; --"10101",
process (clk32)
variable bit_clk_cnt : std_logic_vector(7 downto 0) := (others => '0');
begin
if rising_edge(clk32) then
mode_r1 <= mode;
if (mode_r1 xor mode) = '1' then -- read <-> write change
bit_clk_cnt := (others => '0');
byte_n <= '1';
bit_clk_en <= '0';
else
bit_clk_en <= '0';
if bit_clk_cnt = X"6F" then
bit_clk_en <= '1';
bit_clk_cnt := (others => '0');
else
bit_clk_cnt := bit_clk_cnt + '1';
end if;
byte_n <= '1';
if byte_in_n = '0' and mtr = '1' and ram_ready = '1' then
if bit_clk_cnt > X"10" then
if bit_clk_cnt < X"5E" then
byte_n <= '0';
end if;
end if;
end if;
end if;
end if;
end process;
read_write_process : process (clk32, bit_clk_en)
begin
if rising_edge(clk32) then
ram_we <= '0';
if bit_clk_en = '1' then
mode_r2 <= mode;
if mode = '1' then autorise_write <= '0'; end if;
if (mode xor mode_r2) = '1' then
if mode = '1' then -- leaving write mode
sync_in_n <= '0';
sync_cnt <= (others => '0');
state <= '0';
else -- entering write mode
byte_cnt <= (others => '0');
nibble <= '0';
gcr_bit_cnt <= (others => '0');
bit_cnt <= (others => '0');
gcr_byte <= (others => '0');
data_cks <= (others => '0');
end if;
end if;
if sync_in_n = '0' and mode = '1' then
byte_cnt <= (others => '0');
nibble <= '0';
gcr_bit_cnt <= (others => '0');
bit_cnt <= (others => '0');
dout <= (others => '0');
gcr_byte <= (others => '0');
data_cks <= (others => '0');
if sync_cnt = X"31" then
sync_cnt <= (others => '0');
sync_in_n <= '1';
else
sync_cnt <= sync_cnt + '1';
end if;
end if;
if sync_in_n = '1' or mode = '0' then
gcr_bit_cnt <= gcr_bit_cnt + '1';
if gcr_bit_cnt = X"4" then
gcr_bit_cnt <= (others => '0');
if nibble = '1' then
nibble <= '0';
byte_addr <= byte_cnt(7 downto 0);
if byte_cnt = "000000000" then
data_cks <= (others => '0');
else
data_cks <= data_cks xor data;
end if;
if mode = '1' or (mode = '0' and autorise_count = '1') then
byte_cnt <= byte_cnt + '1';
end if;
else
nibble <= '1';
if mode = '0' and ram_di = X"07" then
autorise_write <= '1';
autorise_count <= '1';
end if;
if byte_cnt >= "100000000" then
autorise_write <= '0';
autorise_count <= '0';
end if;
end if;
end if;
bit_cnt <= bit_cnt + '1';
byte_in_n <= '1';
if bit_cnt = X"7" then
byte_in_n <= '0';
gcr_byte_out <= din;
end if;
if state = '0' then
if byte_cnt = "000010000" then
sync_in_n <= '0';
state<= '1';
end if;
else
if byte_cnt = "100010001" then
sync_in_n <= '0';
state <= '0';
if sector_dbl = sector_max then
sector_dbl <= (others=>'0');
else
sector_dbl <= sector_dbl + '1';
end if;
end if;
end if;
-- demux byte from floppy (ram)
gcr_byte <= gcr_byte(6 downto 0) & gcr_bit;
if bit_cnt = X"7" then
dout <= gcr_byte(6 downto 0) & gcr_bit;
end if;
-- serialise/convert byte to floppy (ram)
gcr_nibble_out <= gcr_nibble_out(3 downto 0) & gcr_bit_out;
if gcr_bit_cnt = X"0" then
if nibble = '0' then
ram_di(3 downto 0) <= nibble_out;
else
ram_di(7 downto 4) <= nibble_out;
end if;
end if;
if gcr_bit_cnt = X"1" and nibble = '0' then
if autorise_write = '1' then
ram_we <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end struct;

View File

@@ -121,23 +121,20 @@ component sram is port
);
end component;
---------
-- Mist IO
---------
-- config string used by the io controller to fill the OSD
--constant CONF_STR : string := "C64;PRG;S1,D64;O2,Video standard,PAL,NTSC;O8A,Scandoubler Fx,None,HQ2x-320,HQ2x-160,CRT 25%,CRT 50%;O3,Joysticks,normal,swapped;O6,Audio filter,On,Off;T5,Reset;V0,v0.27.33";
constant CONF_STR : string := "C64;;"&
"S,D64,Mount Disk;"&
"F,PRG,Load File;"&
"F,CRT,Load Cartridge;" &
"O2,Video standard,PAL,NTSC;"&
"O8A,Scandoubler Fx,None,HQ2x-320,HQ2x-160,CRT 25%,CRT 50%;"&
"O3,Joysticks,normal,swapped;"&
"O6,Audio filter,On,Off;"&
--"OB,BIOS,C64,C64GS;" &
--"T5,Reset;"&
"V0,v0.30.30";
constant CONF_STR : string :=
"C64;;"&
"S,D64,Mount Disk;"&
"F,PRG,Load File;"&
"F,CRT,Load Cartridge;" &--3
-- "F,TAP,Load File;"&--4
-- "F,T64,Load File;"&--5
"O2,Video standard,PAL,NTSC;"&
"O8A,Scandoubler Fx,None,HQ2x-320,HQ2x-160,CRT 25%,CRT 50%;"&
"O3,Joysticks,normal,swapped;"&
"O6,Audio filter,On,Off;"&
-- "OB,BIOS,C64,C64GS;" &
"T5,Reset & Detach Cartridge;"&
"V0,v0.35.00";
-- convert string to std_logic_vector to be given to user_io
function to_slv(s: string) return std_logic_vector is
@@ -278,14 +275,15 @@ end component;
---------
-- audio
---------
--------
component sigma_delta_dac port
(
CLK : in std_logic;
RESET : in std_logic;
DACin : in std_logic_vector(14 downto 0);
DACout : out std_logic
clk : in std_logic;
ldatasum : in std_logic_vector(14 downto 0);
rdatasum : in std_logic_vector(14 downto 0);
aleft : out std_logic;
aright : out std_logic
);
end component sigma_delta_dac;
@@ -431,7 +429,6 @@ end component cartridge;
signal sd_change : std_logic;
signal disk_readonly : std_logic;
signal old_download : std_logic;
-- these need to be redirected to the SDRAM
signal sdram_we : std_logic;
signal sdram_ce : std_logic;
@@ -483,7 +480,7 @@ end component cartridge;
signal hsync_out : std_logic;
signal vsync_out : std_logic;
signal audio_data : std_logic_vector(17 downto 0);
signal audio_data : std_logic_vector(15 downto 0);
signal reset_counter : integer;
signal reset_n : std_logic;
@@ -492,7 +489,6 @@ end component cartridge;
signal nmi : std_logic;
signal nmi_ack : std_logic;
signal erasing : std_logic;
-- temporary signal to extend c64_addr to 24bit LCA
signal c64_addr_temp : std_logic_vector(24 downto 0);
signal cart_blk_len : std_logic_vector(31 downto 0);
signal cart_hdr_cnt : std_logic_vector(3 downto 0);
@@ -503,7 +499,7 @@ end component cartridge;
begin
-- 1541 activity led
LED <= not led_disk;
LED <= not ioctl_download;
iec_cycle <= '1' when ces = "1011" else '0';
@@ -638,7 +634,7 @@ begin
end if;
if ioctl_wr='1' then
if ioctl_index = 2 then
if ioctl_index = 2 then--prg
if ioctl_addr = 0 then
ioctl_load_addr(7 downto 0) <= ioctl_data;
elsif(ioctl_addr = 1) then
@@ -688,6 +684,15 @@ begin
ioctl_ram_wr <= '1';
end if;
end if;
if ioctl_index = 4 then
if ioctl_addr = 0 then
ioctl_load_addr <= '0' & X"200000";
ioctl_ram_data <= ioctl_data;
else
ioctl_ram_wr <= '1';
end if;
end if;
end if;
end if;
@@ -806,29 +811,21 @@ begin
ce => sdram_ce
);
dac : sigma_delta_dac
port map (
clk => clk32,
ldatasum => audio_data(15 downto 1),
rdatasum => audio_data(15 downto 1),
aleft => AUDIO_L,
aright => AUDIO_R
);
-- decode audio
dac_l : sigma_delta_dac
port map (
CLK => clk32,
DACin => not audio_data(17) & audio_data(16 downto 3),
DACout => AUDIO_L,
RESET => '0'
);
dac_r : sigma_delta_dac
port map (
CLK => clk32,
DACin => not audio_data(17) & audio_data(16 downto 3),
DACout => AUDIO_R,
RESET => '0'
);
fpga64 : entity work.fpga64_sid_iec
port map(
clk32 => clk32,
reset_n => reset_n,
c64gs => status(11),
c64gs => status(11),-- not enough BRAM
kbd_clk => not ps2_clk,
kbd_dat => ps2_dat,
ramAddr => c64_addr_int,
@@ -873,12 +870,12 @@ begin
iec_clk_o => c64_iec_clk_o,
iec_data_i => not c64_iec_data_i,
iec_clk_i => not c64_iec_clk_i,
iec_atn_i => not c64_iec_atn_i,
-- iec_atn_i => not c64_iec_atn_i,
disk_num => open,
c64rom_addr => ioctl_addr(13 downto 0),
c64rom_data => ioctl_data,
c64rom_wr => c64rom_wr,
cart_detach_key => cart_detach_key,
-- cart_detach_key => cart_detach_key,
reset_key => reset_key
);

View File

@@ -141,7 +141,8 @@ begin
rdaddress => std_logic_vector(cpuAddr(14) & cpuAddr(12 downto 0)),
q => romData_c64
);
-- not enough BRAM on MIST FPGA
-- kernelromGS: entity work.rom_GS64
-- port map
-- (
@@ -157,6 +158,7 @@ begin
romData <= romData_c64gs when c64gs_ena = '1' else romData_c64;
process(clk)
begin
if rising_edge(clk) then

View File

@@ -91,9 +91,9 @@ entity fpga64_sid_iec is
ces : out std_logic_vector(3 downto 0);
--Connector to the SID
SIDclk : out std_logic;
SIDclk : buffer std_logic;
still : out unsigned(15 downto 0);
audio_data : out std_logic_vector(17 downto 0);
audio_data : out std_logic_vector(15 downto 0);
extfilter_en: in std_logic;
-- IEC
@@ -102,7 +102,7 @@ entity fpga64_sid_iec is
iec_clk_o : out std_logic;
iec_clk_i : in std_logic;
iec_atn_o : out std_logic;
iec_atn_i : in std_logic;
-- iec_atn_i : in std_logic;
disk_num : out std_logic_vector(7 downto 0);
@@ -212,6 +212,10 @@ architecture rtl of fpga64_sid_iec is
signal cpuDi: unsigned(7 downto 0);
signal cpuDo: unsigned(7 downto 0);
signal cpuIO: unsigned(7 downto 0);
signal ioF_ext: std_logic;
signal ioE_ext: std_logic;
signal io_data: unsigned(7 downto 0);
signal vicDi: unsigned(7 downto 0);
signal vicAddr: unsigned(15 downto 0);
@@ -246,9 +250,28 @@ architecture rtl of fpga64_sid_iec is
signal ntscMode : std_logic;
signal ntscModeInvert : std_logic := '0' ;
signal restore_key : std_logic;
signal clk_1MHz : std_logic_vector(31 downto 0);
signal voice_volume : signed(17 downto 0);
signal pot_x : std_logic_vector(7 downto 0);
signal pot_y : std_logic_vector(7 downto 0);
component sid8580
port (
reset : in std_logic;
clk : in std_logic;
ce_1m : in std_logic;
we : in std_logic;
addr : in std_logic_vector(4 downto 0);
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
pot_x : in std_logic_vector(7 downto 0);
pot_y : in std_logic_vector(7 downto 0);
audio_data : out std_logic_vector(15 downto 0);
extfilter_en : in std_logic
);
end component sid8580;
begin
-- -----------------------------------------------------------------------
-- Local signal to outside world
@@ -402,6 +425,9 @@ begin
max_ram => max_ram,
ramData => ramDataReg,
-- ioF_ext => ioF_ext,
-- ioE_ext => ioE_ext,
-- io_data => io_data,
cpuWe => cpuWe,
cpuAddr => cpuAddr,
@@ -523,7 +549,7 @@ begin
-- -----------------------------------------------------------------------
-- SID
-- -----------------------------------------------------------------------
div1m: process(clk32) -- this process devides 32 MHz to 1MHz (for the SID)
div1m: process(clk32) -- this process devides 32 MHz to 1MHz (for the SID)
begin
if (rising_edge(clk32)) then
if (reset = '1') then
@@ -535,30 +561,23 @@ begin
end if;
end process;
audio_data <= std_logic_vector(voice_volume);
sid: entity work.sid_top
sid_8580 : sid8580
port map (
clock => clk32,
reset => reset,
addr => "000" & cpuAddr(4 downto 0),
wren => pulseWrRam and phi0_cpu and cs_sid,
wdata => std_logic_vector(cpuDo),
rdata => sid_do,
potx => not std_logic((cia1_pao(7) and JoyA(5)) or (cia1_pao(6) and JoyB(5))),
poty => not std_logic((cia1_pao(7) and JoyA(6)) or (cia1_pao(6) and JoyB(6))),
comb_wave_l => '0',
comb_wave_r => '0',
extfilter_en => extfilter_en,
start_iter => clk_1MHz(31),
sample_left => voice_volume,
sample_right => open
clk => clk32,
ce_1m => clk_1MHz(31),
we => pulseWrRam and phi0_cpu and cs_sid,
addr => std_logic_vector(cpuAddr(4 downto 0)),
data_in => std_logic_vector(cpuDo),
data_out => sid_do,
pot_x => pot_x,
pot_y => pot_y,
audio_data => audio_data,
extfilter_en => extfilter_en
);
pot_x <= X"FF" when ((cia1_pao(7) and JoyA(5)) or (cia1_pao(6) and JoyB(5))) = '0' else X"00";
pot_y <= X"FF" when ((cia1_pao(7) and JoyA(6)) or (cia1_pao(6) and JoyB(6))) = '0' else X"00";
-- -----------------------------------------------------------------------
-- CIAs
-- -----------------------------------------------------------------------

View File

@@ -0,0 +1,226 @@
module sid8580
(
input reset,
input clk,
input ce_1m,
input we,
input [4:0] addr,
input [7:0] data_in,
output [ 7:0] data_out,
input [7:0] pot_x,
input [7:0] pot_y,
input extfilter_en,
output [15:0] audio_data
);
// Internal Signals
reg [7:0] Voice_1_Freq_lo;
reg [7:0] Voice_1_Freq_hi;
reg [7:0] Voice_1_Pw_lo;
reg [3:0] Voice_1_Pw_hi;
reg [7:0] Voice_1_Control;
reg [7:0] Voice_1_Att_dec;
reg [7:0] Voice_1_Sus_Rel;
reg [7:0] Voice_2_Freq_lo;
reg [7:0] Voice_2_Freq_hi;
reg [7:0] Voice_2_Pw_lo;
reg [3:0] Voice_2_Pw_hi;
reg [7:0] Voice_2_Control;
reg [7:0] Voice_2_Att_dec;
reg [7:0] Voice_2_Sus_Rel;
reg [7:0] Voice_3_Freq_lo;
reg [7:0] Voice_3_Freq_hi;
reg [7:0] Voice_3_Pw_lo;
reg [3:0] Voice_3_Pw_hi;
reg [7:0] Voice_3_Control;
reg [7:0] Voice_3_Att_dec;
reg [7:0] Voice_3_Sus_Rel;
reg [7:0] Filter_Fc_lo;
reg [7:0] Filter_Fc_hi;
reg [7:0] Filter_Res_Filt;
reg [7:0] Filter_Mode_Vol;
wire [7:0] Misc_Osc3_Random;
wire [7:0] Misc_Env3;
reg [7:0] do_buf;
reg [7:0] sidrandom;
wire [11:0] voice_1;
wire [11:0] voice_2;
wire [11:0] voice_3;
wire [17:0] voice_mixed;
reg [17:0] voice_volume;
wire voice_1_PA_MSB;
wire voice_2_PA_MSB;
wire voice_3_PA_MSB;
wire [18:0] filtered_audio;
wire [17:0] unsigned_audio;
wire [18:0] unsigned_filt;
localparam DC_offset = 14'b00111111111111;
// Voice 1 Instantiation
sid_voice v1
(
.clock(clk),
.ce_1m(ce_1m),
.reset(reset),
.freq_lo(Voice_1_Freq_lo),
.freq_hi(Voice_1_Freq_hi),
.pw_lo(Voice_1_Pw_lo),
.pw_hi(Voice_1_Pw_hi),
.control(Voice_1_Control),
.att_dec(Voice_1_Att_dec),
.sus_rel(Voice_1_Sus_Rel),
.osc_msb_in(voice_3_PA_MSB),
.osc_msb_out(voice_1_PA_MSB),
.signal_out(voice_1)
);
// Voice 2 Instantiation
sid_voice v2
(
.clock(clk),
.ce_1m(ce_1m),
.reset(reset),
.freq_lo(Voice_2_Freq_lo),
.freq_hi(Voice_2_Freq_hi),
.pw_lo(Voice_2_Pw_lo),
.pw_hi(Voice_2_Pw_hi),
.control(Voice_2_Control),
.att_dec(Voice_2_Att_dec),
.sus_rel(Voice_2_Sus_Rel),
.osc_msb_in(voice_1_PA_MSB),
.osc_msb_out(voice_2_PA_MSB),
.signal_out(voice_2)
);
// Voice 3 Instantiation
sid_voice v3
(
.clock(clk),
.ce_1m(ce_1m),
.reset(reset),
.freq_lo(Voice_3_Freq_lo),
.freq_hi(Voice_3_Freq_hi),
.pw_lo(Voice_3_Pw_lo),
.pw_hi(Voice_3_Pw_hi),
.control(Voice_3_Control),
.att_dec(Voice_3_Att_dec),
.sus_rel(Voice_3_Sus_Rel),
.osc_msb_in(voice_2_PA_MSB),
.osc_msb_out(voice_3_PA_MSB),
.signal_out(voice_3),
.osc_out(Misc_Osc3_Random),
.env_out(Misc_Env3)
);
// Filter Instantiation
sid_filters filters
(
.clk(clk),
.rst(reset),
.Fc_lo(Filter_Fc_lo),
.Fc_hi(Filter_Fc_hi),
.Res_Filt(Filter_Res_Filt),
.Mode_Vol(Filter_Mode_Vol),
.voice1(voice_1),
.voice2(voice_2),
.voice3(voice_3),
.input_valid(ce_1m),
.ext_in(12'hfff),
.sound(audio_data),
.extfilter_en(extfilter_en)
);
assign data_out = do_buf;
//assign audio_data = {1'b0, (filtered_audio[18:5] + 14'b1000000000000000)};
//assign unsigned_filt = filtered_audio + 19'b1000000000000000000;
//assign unsigned_audio = unsigned_filt[18:1];
//assign audio_data = filtered_audio[18:3];// + 15'h4000;//{1'b0, unsigned_audio[17:1]};
always @(*) begin
case (addr)
5'h19: do_buf = pot_x;
5'h1a: do_buf = pot_y;
5'h1b: do_buf = Misc_Osc3_Random;
5'h1c: do_buf = Misc_Env3;
default: do_buf = 0;
endcase
end
// Register Decoding
always @(posedge clk) begin
if (reset) begin
Voice_1_Freq_lo <= 0;
Voice_1_Freq_hi <= 0;
Voice_1_Pw_lo <= 0;
Voice_1_Pw_hi <= 0;
Voice_1_Control <= 0;
Voice_1_Att_dec <= 0;
Voice_1_Sus_Rel <= 0;
Voice_2_Freq_lo <= 0;
Voice_2_Freq_hi <= 0;
Voice_2_Pw_lo <= 0;
Voice_2_Pw_hi <= 0;
Voice_2_Control <= 0;
Voice_2_Att_dec <= 0;
Voice_2_Sus_Rel <= 0;
Voice_3_Freq_lo <= 0;
Voice_3_Freq_hi <= 0;
Voice_3_Pw_lo <= 0;
Voice_3_Pw_hi <= 0;
Voice_3_Control <= 0;
Voice_3_Att_dec <= 0;
Voice_3_Sus_Rel <= 0;
Filter_Fc_lo <= 0;
Filter_Fc_hi <= 0;
Filter_Res_Filt <= 0;
Filter_Mode_Vol <= 0;
end
else begin
if (we) begin
case (addr)
5'h00: Voice_1_Freq_lo <= data_in;
5'h01: Voice_1_Freq_hi <= data_in;
5'h02: Voice_1_Pw_lo <= data_in;
5'h03: Voice_1_Pw_hi <= data_in[3:0];
5'h04: Voice_1_Control <= data_in;
5'h05: Voice_1_Att_dec <= data_in;
5'h06: Voice_1_Sus_Rel <= data_in;
5'h07: Voice_2_Freq_lo <= data_in;
5'h08: Voice_2_Freq_hi <= data_in;
5'h09: Voice_2_Pw_lo <= data_in;
5'h0a: Voice_2_Pw_hi <= data_in[3:0];
5'h0b: Voice_2_Control <= data_in;
5'h0c: Voice_2_Att_dec <= data_in;
5'h0d: Voice_2_Sus_Rel <= data_in;
5'h0e: Voice_3_Freq_lo <= data_in;
5'h0f: Voice_3_Freq_hi <= data_in;
5'h10: Voice_3_Pw_lo <= data_in;
5'h11: Voice_3_Pw_hi <= data_in[3:0];
5'h12: Voice_3_Control <= data_in;
5'h13: Voice_3_Att_dec <= data_in;
5'h14: Voice_3_Sus_Rel <= data_in;
5'h15: Filter_Fc_lo <= data_in;
5'h16: Filter_Fc_hi <= data_in;
5'h17: Filter_Res_Filt <= data_in;
5'h18: Filter_Mode_Vol <= data_in;
endcase
end
end
end
endmodule

View File

@@ -0,0 +1,178 @@
module sid_envelope
(
input clock,
input ce_1m,
input reset,
input gate,
input [ 7:0] att_dec,
input [ 7:0] sus_rel,
output reg [7:0] envelope
);
// Internal Signals
reg [ 1:0] state;
reg gate_edge;
reg [14:0] rate_counter;
reg [14:0] rate_period;
wire [14:0] adsrtable [0:15];
reg [ 7:0] exponential_counter;
reg [ 7:0] exponential_counter_period;
reg hold_zero;
reg envelope_pipeline;
`define ST_ATTACK 2'b00
`define ST_DEC_SUS 2'b01
`define ST_RELEASE 2'b10
assign adsrtable[4'h0] = 15'h007f;
assign adsrtable[4'h1] = 15'h3000;
assign adsrtable[4'h2] = 15'h1e00;
assign adsrtable[4'h3] = 15'h0660;
assign adsrtable[4'h4] = 15'h0182;
assign adsrtable[4'h5] = 15'h5573;
assign adsrtable[4'h6] = 15'h000e;
assign adsrtable[4'h7] = 15'h3805;
assign adsrtable[4'h8] = 15'h2424;
assign adsrtable[4'h9] = 15'h2220;
assign adsrtable[4'ha] = 15'h090c;
assign adsrtable[4'hb] = 15'h0ecd;
assign adsrtable[4'hc] = 15'h010e;
assign adsrtable[4'hd] = 15'h23f7;
assign adsrtable[4'he] = 15'h5237;
assign adsrtable[4'hf] = 15'h64a8;
// State Logic
always @(posedge clock) begin
if (reset)
state <= `ST_RELEASE;
else if(ce_1m) begin
if (gate_edge != gate)
if (gate) state <= `ST_ATTACK;
else state <= `ST_RELEASE;
if (((rate_counter == rate_period) &&
(state == `ST_ATTACK ||
(exponential_counter + 1'b1) == exponential_counter_period) &&
(!hold_zero)))
case (state)
`ST_ATTACK: if (envelope + 1'b1 == 8'hff) state <= `ST_DEC_SUS;
endcase
end
end
// Gate Switch Detection
always @(posedge clock) begin
if (reset) gate_edge <= 1'b0;
else if(ce_1m) begin
if (gate_edge != gate) gate_edge <= gate;
end
end
// Envelope
always @(posedge clock) begin
if (reset)
envelope <= 8'h00;
else if(ce_1m) begin
if (envelope_pipeline) envelope <= envelope - 1'b1;
if (((rate_counter == rate_period) &&
(state == `ST_ATTACK ||
(exponential_counter + 1'b1) == exponential_counter_period) &&
(!hold_zero)))
case (state)
`ST_ATTACK: envelope <= envelope + 1'b1;
`ST_DEC_SUS: if (envelope != {2{sus_rel[7:4]}} && exponential_counter_period == 1) envelope <= envelope - 1'b1;
`ST_RELEASE: if (exponential_counter_period == 1) envelope <= envelope - 1'b1;
endcase
end
end
// Envelope Pipeline
always @(posedge clock) begin
if (reset)
envelope_pipeline <= 1'b0;
else if(ce_1m) begin
if (gate_edge != gate)
if (gate) envelope_pipeline <= 1'b0;
if (envelope_pipeline) envelope_pipeline <= 1'b0;
if (((rate_counter == rate_period) &&
(state == `ST_ATTACK ||
(exponential_counter + 1'b1) == exponential_counter_period) &&
(!hold_zero)))
case (state)
`ST_DEC_SUS: if (envelope != {2{sus_rel[7:4]}} && exponential_counter_period != 1) envelope_pipeline <= 1'b1;
`ST_RELEASE: if(exponential_counter_period != 1) envelope_pipeline <= 1'b1;
endcase
end
end
// Exponential Counter
always @(posedge clock) begin
if (reset)
exponential_counter <= 8'h00;
else if(ce_1m) begin
if (rate_counter == rate_period) begin
exponential_counter <= exponential_counter + 1'b1;
if (state == `ST_ATTACK || (exponential_counter + 1'b1) == exponential_counter_period) exponential_counter <= 8'h00;
end
end
end
// Exponential Counter Period
always @(posedge clock) begin
if (reset) begin
hold_zero <= 1'b1;
exponential_counter_period <= 8'h00;
end
else if(ce_1m) begin
if (gate_edge != gate) if (gate) hold_zero <= 1'b0;
if ((envelope_pipeline) || ((rate_counter == rate_period) &&
(state == `ST_ATTACK ||
(exponential_counter + 1'b1) == exponential_counter_period) &&
(!hold_zero)))
begin
case (state == `ST_ATTACK ? envelope + 1'b1 : envelope - 1'b1)
8'hff: exponential_counter_period <= 8'd1;
8'h5d: exponential_counter_period <= 8'd2;
8'h36: exponential_counter_period <= 8'd4;
8'h1a: exponential_counter_period <= 8'd8;
8'h0e: exponential_counter_period <= 8'd16;
8'h06: exponential_counter_period <= 8'd30;
8'h00: begin
exponential_counter_period <= 8'd1;
hold_zero <= 1'b1;
end
endcase
end
end
end
// Rate Counter
always @(posedge clock) begin
if (reset) rate_counter <= 15'h7fff;
else if(ce_1m) begin
if (rate_counter == rate_period) rate_counter <= 15'h7fff;
else rate_counter <= {rate_counter[1] ^ rate_counter[0], rate_counter[14:1]};
end
end
// Rate Period
always @(posedge clock) begin
if (reset)
rate_period <= adsrtable[sus_rel[3:0]];
else if(ce_1m) begin
if (gate_edge != gate) begin
if (gate) rate_period <= adsrtable[att_dec[7:4]];
else rate_period <= adsrtable[sus_rel[3:0]];
end
case (state)
`ST_ATTACK: rate_period <= adsrtable[att_dec[7:4]];
`ST_DEC_SUS: rate_period <= adsrtable[att_dec[3:0]];
default: rate_period <= adsrtable[sus_rel[3:0]];
endcase
end
end
endmodule

View File

@@ -0,0 +1,129 @@
module sid_filters
(
input clk,
input rst,
input [ 7:0] Fc_lo,
input [ 7:0] Fc_hi,
input [ 7:0] Res_Filt,
input [ 7:0] Mode_Vol,
input [11:0] voice1,
input [11:0] voice2,
input [11:0] voice3,
input input_valid,
input [11:0] ext_in,
input extfilter_en,
output reg [15:0] sound
);
reg signed [17:0] Vhp;
reg signed [17:0] Vbp;
reg signed [17:0] w0;
reg signed [17:0] q;
wire [10:0] divmul[16];
assign divmul[0] = 1448;
assign divmul[1] = 1328;
assign divmul[2] = 1218;
assign divmul[3] = 1117;
assign divmul[4] = 1024;
assign divmul[5] = 939;
assign divmul[6] = 861;
assign divmul[7] = 790;
assign divmul[8] = 724;
assign divmul[9] = 664;
assign divmul[10] = 609;
assign divmul[11] = 558;
assign divmul[12] = 512;
assign divmul[13] = 470;
assign divmul[14] = 431;
assign divmul[15] = 395;
wire [35:0] mul1 = w0 * Vhp;
wire [35:0] mul2 = w0 * Vbp;
wire [35:0] mul3 = q * Vbp;
wire [35:0] mul4 = 18'd82355 * ({Fc_hi, Fc_lo[2:0]} + 1'b1);
// Filter
always @(posedge clk) begin
reg [17:0] dVbp;
reg [17:0] Vlp;
reg [17:0] dVlp;
reg [17:0] Vi;
reg [17:0] Vnf;
reg [17:0] Vf;
reg [21:0] mulr;
reg [3:0] state;
if (rst) begin
state <= 0;
Vlp <= 0;
Vbp <= 0;
Vhp <= 0;
end
else begin
case (state)
0: if (input_valid) begin
if(mulr[21] == mulr[20]) sound <= mulr[20:5];
state <= state + 1'd1;
Vi <= 0;
Vnf <= 0;
end
1: state <= state + 1'd1;
2: begin
state <= state + 1'd1;
w0 <= {mul4[35], mul4[28:12]};
if (Res_Filt[0]) Vi <= Vi + (voice1 << 2);
else Vnf <= Vnf + (voice1 << 2);
end
3: begin
state <= state + 1'd1;
if (Res_Filt[1]) Vi <= Vi + (voice2 << 2);
else Vnf <= Vnf + (voice2 << 2);
end
4: begin
state <= state + 1'd1;
if (Res_Filt[2]) Vi <= Vi + (voice3 << 2);
else if (!Mode_Vol[7]) Vnf <= Vnf + (voice3 << 2);
dVbp <= {mul1[35], mul1[35:19]};
end
5: begin
state <= state + 1'd1;
if (Res_Filt[3]) Vi <= Vi + (ext_in << 2);
else Vnf <= Vnf + (ext_in << 2);
dVlp <= {mul2[35], mul2[35:19]};
Vbp <= Vbp - dVbp;
q <= divmul[Res_Filt[7:4]];
end
6: begin
state <= state + 1'd1;
Vlp <= Vlp - dVlp;
Vf <= (Mode_Vol[5]) ? Vbp : 18'h00000;
end
7: begin
state <= state + 1'd1;
Vhp <= {mul3[35], mul3[26:10]} - Vlp;
if(Mode_Vol[4]) Vf <= Vf + Vlp;
end
8: begin
state <= state + 1'd1;
Vhp <= Vhp - Vi;
end
9: begin
state <= state + 1'd1;
if(Mode_Vol[6]) Vf <= Vf + Vhp;
end
10: begin
state <= state + 1'd1;
Vf <= (extfilter_en) ? {~Vf + 1'b1} + Vnf : Vi + Vnf;
end
11: begin
state <= 0;
mulr <= Vf * Mode_Vol[3:0];
end
endcase
end
end
endmodule

View File

@@ -0,0 +1,353 @@
// altera message_off 10030
module sid_voice
(
input clock,
input ce_1m,
input reset,
input [7:0] freq_lo,
input [7:0] freq_hi,
input [7:0] pw_lo,
input [3:0] pw_hi,
input [7:0] control,
input [7:0] att_dec,
input [7:0] sus_rel,
input osc_msb_in,
output osc_msb_out,
output [11:0] signal_out,
output [ 7:0] osc_out,
output [ 7:0] env_out
);
// Internal Signals
reg [23:0] oscillator;
reg osc_edge;
reg osc_msb_in_prv;
reg [11:0] triangle;
reg [11:0] sawtooth;
reg [11:0] pulse;
reg [11:0] noise;
reg [22:0] lfsr_noise;
wire [ 7:0] envelope;
reg [11:0] wave_out;
reg [19:0] dca_out;
`define noise_ctrl control[7]
`define pulse_ctrl control[6]
`define saw_ctrl control[5]
`define tri_ctrl control[4]
`define test_ctrl control[3]
`define ringmod_ctrl control[2]
`define sync_ctrl control[1]
// Signal Assignments
assign osc_msb_out = oscillator[23];
assign signal_out = dca_out[19:8];
assign osc_out = wave_out[11:4];
assign env_out = envelope;
// Digital Controlled Amplifier
always @(posedge clock) if(ce_1m) dca_out <= wave_out * envelope;
// Envelope Instantiation
sid_envelope adsr
(
.clock(clock),
.ce_1m(ce_1m),
.reset(reset),
.gate(control[0]),
.att_dec(att_dec),
.sus_rel(sus_rel),
.envelope(envelope)
);
// Phase Accumulating Oscillator
always @(posedge clock) begin
if(ce_1m) begin
osc_msb_in_prv <= osc_msb_in;
if (reset || `test_ctrl || ((`sync_ctrl) && (!osc_msb_in) && (osc_msb_in != osc_msb_in_prv)))
oscillator <= 0;
else
oscillator <= oscillator + {freq_hi, freq_lo};
end
end
// Waveform Generator
always @(posedge clock) begin
if (reset) begin
triangle <= 0;
sawtooth <= 0;
pulse <= 0;
noise <= 0;
osc_edge <= 0;
lfsr_noise <= 23'h7fffff;
end
else if(ce_1m) begin
triangle <= (`ringmod_ctrl) ?
{({11{osc_msb_in}} ^ {{11{oscillator[23]}}}) ^ oscillator[22:12], 1'b0} :
{{11{oscillator[23]}} ^ oscillator[22:12], 1'b0};
sawtooth <= oscillator[23:12];
pulse <= (`test_ctrl) ? 12'hfff :
(oscillator[23:12] >= {pw_hi, pw_lo}) ? {12{1'b1}} :
{12{1'b0}};
noise <= {lfsr_noise[21], lfsr_noise[19], lfsr_noise[15],
lfsr_noise[12], lfsr_noise[10], lfsr_noise[6],
lfsr_noise[3], lfsr_noise[1], 4'b0000};
osc_edge <= (oscillator[19] && !osc_edge) ? 1'b1 :
(!oscillator[19] && osc_edge) ? 1'b0 :
osc_edge;
lfsr_noise <= (oscillator[19] && !osc_edge) ?
{lfsr_noise[21:0], (lfsr_noise[22] | `test_ctrl) ^ lfsr_noise[17]} :
lfsr_noise;
end
end
// Waveform Output Selector
always @(*) begin
case (control[7:4])
4'b0001: wave_out = triangle;
4'b0010: wave_out = sawtooth;
4'b0011: wave_out = {wave__st[sawtooth], 4'b0000};
4'b0100: wave_out = pulse;
4'b0101: wave_out = {wave_p_t[triangle[11:1]], 4'b0000} & pulse;
4'b0110: wave_out = {wave_ps_[sawtooth], 4'b0000} & pulse;
4'b0111: wave_out = {wave_pst[sawtooth], 4'b0000} & pulse;
4'b1000: wave_out = noise;
default: wave_out = 0;
endcase
end
//
// convert combinatorial logic to ROM (Sorgelig)
//
reg [7:0] wave__st[4096];
reg [7:0] wave_p_t[2048];
reg [7:0] wave_ps_[4096];
reg [7:0] wave_pst[4096];
initial begin
integer i;
for(i = 0; i<4096; i=i+1) wave__st[i] =
(i < 'h07e) ? 8'h00 : (i < 'h080) ? 8'h03 : (i < 'h0fc) ? 8'h00 : (i < 'h100) ? 8'h07 :
(i < 'h17e) ? 8'h00 : (i < 'h180) ? 8'h03 : (i < 'h1f8) ? 8'h00 : (i < 'h1fc) ? 8'h0e :
(i < 'h200) ? 8'h0f : (i < 'h27e) ? 8'h00 : (i < 'h280) ? 8'h03 : (i < 'h2fc) ? 8'h00 :
(i < 'h300) ? 8'h07 : (i < 'h37e) ? 8'h00 : (i < 'h380) ? 8'h03 : (i < 'h3bf) ? 8'h00 :
(i < 'h3c0) ? 8'h01 : (i < 'h3f0) ? 8'h00 : (i < 'h3f8) ? 8'h1c : (i < 'h3fa) ? 8'h1e :
(i < 'h400) ? 8'h1f : (i < 'h47e) ? 8'h00 : (i < 'h480) ? 8'h03 : (i < 'h4fc) ? 8'h00 :
(i < 'h500) ? 8'h07 : (i < 'h57e) ? 8'h00 : (i < 'h580) ? 8'h03 : (i < 'h5f8) ? 8'h00 :
(i < 'h5fc) ? 8'h0e : (i < 'h5ff) ? 8'h0f : (i < 'h600) ? 8'h1f : (i < 'h67e) ? 8'h00 :
(i < 'h680) ? 8'h03 : (i < 'h6fc) ? 8'h00 : (i < 'h700) ? 8'h07 : (i < 'h77e) ? 8'h00 :
(i < 'h780) ? 8'h03 : (i < 'h7bf) ? 8'h00 : (i < 'h7c0) ? 8'h01 : (i < 'h7e0) ? 8'h00 :
(i < 'h7f0) ? 8'h38 : (i < 'h7f7) ? 8'h3c : (i < 'h7f8) ? 8'h3e : (i < 'h800) ? 8'h7f :
(i < 'h87e) ? 8'h00 : (i < 'h880) ? 8'h03 : (i < 'h8fc) ? 8'h00 : (i < 'h900) ? 8'h07 :
(i < 'h97e) ? 8'h00 : (i < 'h980) ? 8'h03 : (i < 'h9f8) ? 8'h00 : (i < 'h9fc) ? 8'h0e :
(i < 'ha00) ? 8'h0f : (i < 'ha7e) ? 8'h00 : (i < 'ha80) ? 8'h03 : (i < 'hafc) ? 8'h00 :
(i < 'hb00) ? 8'h07 : (i < 'hb7e) ? 8'h00 : (i < 'hb80) ? 8'h03 : (i < 'hbbf) ? 8'h00 :
(i < 'hbc0) ? 8'h01 : (i < 'hbf0) ? 8'h00 : (i < 'hbf8) ? 8'h1c : (i < 'hbfa) ? 8'h1e :
(i < 'hbfe) ? 8'h1f : (i < 'hc00) ? 8'h3f : (i < 'hc7e) ? 8'h00 : (i < 'hc80) ? 8'h03 :
(i < 'hcfc) ? 8'h00 : (i < 'hd00) ? 8'h07 : (i < 'hd7e) ? 8'h00 : (i < 'hd80) ? 8'h03 :
(i < 'hdbf) ? 8'h00 : (i < 'hdc0) ? 8'h01 : (i < 'hdf8) ? 8'h00 : (i < 'hdfc) ? 8'h0e :
(i < 'hdfe) ? 8'h0f : (i < 'he00) ? 8'h1f : (i < 'he7c) ? 8'h00 : (i < 'he7d) ? 8'h80 :
(i < 'he7e) ? 8'h00 : (i < 'he80) ? 8'h83 : (i < 'hefc) ? 8'h80 : (i < 'heff) ? 8'h87 :
(i < 'hf00) ? 8'h8f : (i < 'hf01) ? 8'hc0 : (i < 'hf03) ? 8'he0 : (i < 'hf05) ? 8'hc0 :
(i < 'hf09) ? 8'he0 : (i < 'hf11) ? 8'hc0 : (i < 'hf13) ? 8'he0 : (i < 'hf18) ? 8'hc0 :
(i < 'hf19) ? 8'he0 : (i < 'hf21) ? 8'hc0 : (i < 'hf23) ? 8'he0 : (i < 'hf25) ? 8'hc0 :
(i < 'hf2b) ? 8'he0 : (i < 'hf2c) ? 8'hc0 : (i < 'hf2d) ? 8'he0 : (i < 'hf2e) ? 8'hc0 :
(i < 'hf7e) ? 8'he0 : (i < 'hf80) ? 8'he3 : (i < 'hfbf) ? 8'hf0 : (i < 'hfc0) ? 8'hf1 :
(i < 'hfe0) ? 8'hf8 : (i < 'hff0) ? 8'hfc : (i < 'hff8) ? 8'hfe : 8'hff;
for(i = 0; i<2048; i=i+1) wave_p_t[i] =
(i < 'h0ff) ? 8'h00 : (i < 'h100) ? 8'h07 : (i < 'h1fb) ? 8'h00 : (i < 'h1fc) ? 8'h1c :
(i < 'h1fd) ? 8'h00 : (i < 'h1fe) ? 8'h3c : (i < 'h200) ? 8'h3f : (i < 'h2fd) ? 8'h00 :
(i < 'h2fe) ? 8'h0c : (i < 'h2ff) ? 8'h5e : (i < 'h300) ? 8'h5f : (i < 'h377) ? 8'h00 :
(i < 'h378) ? 8'h40 : (i < 'h37b) ? 8'h00 : (i < 'h37d) ? 8'h40 : (i < 'h37f) ? 8'h60 :
(i < 'h380) ? 8'h6f : (i < 'h39f) ? 8'h00 : (i < 'h3a0) ? 8'h40 : (i < 'h3ae) ? 8'h00 :
(i < 'h3b0) ? 8'h40 : (i < 'h3b3) ? 8'h00 : (i < 'h3b7) ? 8'h40 : (i < 'h3b8) ? 8'h60 :
(i < 'h3ba) ? 8'h40 : (i < 'h3be) ? 8'h60 : (i < 'h3bf) ? 8'h70 : (i < 'h3c0) ? 8'h77 :
(i < 'h3c5) ? 8'h00 : (i < 'h3cd) ? 8'h40 : (i < 'h3d0) ? 8'h60 : (i < 'h3d3) ? 8'h40 :
(i < 'h3d7) ? 8'h60 : (i < 'h3d8) ? 8'h70 : (i < 'h3db) ? 8'h60 : (i < 'h3de) ? 8'h70 :
(i < 'h3df) ? 8'h78 : (i < 'h3e0) ? 8'h7b : (i < 'h3e3) ? 8'h60 : (i < 'h3e4) ? 8'h70 :
(i < 'h3e5) ? 8'h60 : (i < 'h3eb) ? 8'h70 : (i < 'h3ef) ? 8'h78 : (i < 'h3f0) ? 8'h7c :
(i < 'h3f3) ? 8'h78 : (i < 'h3f4) ? 8'h7c : (i < 'h3f5) ? 8'h78 : (i < 'h3f7) ? 8'h7c :
(i < 'h3f8) ? 8'h7e : (i < 'h3f9) ? 8'h7c : (i < 'h3fb) ? 8'h7e : (i < 'h400) ? 8'h7f :
(i < 'h47f) ? 8'h00 : (i < 'h480) ? 8'h80 : (i < 'h4bd) ? 8'h00 : (i < 'h4c0) ? 8'h80 :
(i < 'h4cf) ? 8'h00 : (i < 'h4d0) ? 8'h80 : (i < 'h4d7) ? 8'h00 : (i < 'h4d8) ? 8'h80 :
(i < 'h4da) ? 8'h00 : (i < 'h4e0) ? 8'h80 : (i < 'h4e3) ? 8'h00 : (i < 'h4fe) ? 8'h80 :
(i < 'h4ff) ? 8'h8e : (i < 'h500) ? 8'h9f : (i < 'h51f) ? 8'h00 : (i < 'h520) ? 8'h80 :
(i < 'h52b) ? 8'h00 : (i < 'h52c) ? 8'h80 : (i < 'h52d) ? 8'h00 : (i < 'h530) ? 8'h80 :
(i < 'h532) ? 8'h00 : (i < 'h540) ? 8'h80 : (i < 'h543) ? 8'h00 : (i < 'h544) ? 8'h80 :
(i < 'h545) ? 8'h00 : (i < 'h57f) ? 8'h80 : (i < 'h580) ? 8'haf : (i < 'h5bb) ? 8'h80 :
(i < 'h5bf) ? 8'ha0 : (i < 'h5c0) ? 8'hb7 : (i < 'h5cf) ? 8'h80 : (i < 'h5d0) ? 8'ha0 :
(i < 'h5d6) ? 8'h80 : (i < 'h5db) ? 8'ha0 : (i < 'h5dc) ? 8'hb0 : (i < 'h5dd) ? 8'ha0 :
(i < 'h5df) ? 8'hb0 : (i < 'h5e0) ? 8'hbb : (i < 'h5e6) ? 8'ha0 : (i < 'h5e8) ? 8'hb0 :
(i < 'h5e9) ? 8'ha0 : (i < 'h5eb) ? 8'hb0 : (i < 'h5ec) ? 8'hb8 : (i < 'h5ed) ? 8'hb0 :
(i < 'h5ef) ? 8'hb8 : (i < 'h5f0) ? 8'hbc : (i < 'h5f1) ? 8'hb0 : (i < 'h5f5) ? 8'hb8 :
(i < 'h5f7) ? 8'hbc : (i < 'h5f8) ? 8'hbe : (i < 'h5fa) ? 8'hbc : (i < 'h5fb) ? 8'hbe :
(i < 'h5fc) ? 8'hbf : (i < 'h5fd) ? 8'hbe : (i < 'h600) ? 8'hbf : (i < 'h63e) ? 8'h80 :
(i < 'h640) ? 8'hc0 : (i < 'h657) ? 8'h80 : (i < 'h658) ? 8'hc0 : (i < 'h65a) ? 8'h80 :
(i < 'h660) ? 8'hc0 : (i < 'h663) ? 8'h80 : (i < 'h664) ? 8'hc0 : (i < 'h665) ? 8'h80 :
(i < 'h67f) ? 8'hc0 : (i < 'h680) ? 8'hcf : (i < 'h686) ? 8'h80 : (i < 'h689) ? 8'hc0 :
(i < 'h68a) ? 8'h80 : (i < 'h6bf) ? 8'hc0 : (i < 'h6c0) ? 8'hd7 : (i < 'h6dd) ? 8'hc0 :
(i < 'h6df) ? 8'hd0 : (i < 'h6e0) ? 8'hd9 : (i < 'h6e7) ? 8'hc0 : (i < 'h6e8) ? 8'hd0 :
(i < 'h6e9) ? 8'hc0 : (i < 'h6ed) ? 8'hd0 : (i < 'h6ef) ? 8'hd8 : (i < 'h6f0) ? 8'hdc :
(i < 'h6f2) ? 8'hd0 : (i < 'h6f5) ? 8'hd8 : (i < 'h6f7) ? 8'hdc : (i < 'h6f8) ? 8'hde :
(i < 'h6fa) ? 8'hdc : (i < 'h6fb) ? 8'hde : (i < 'h6fc) ? 8'hdf : (i < 'h6fd) ? 8'hde :
(i < 'h700) ? 8'hdf : (i < 'h71b) ? 8'hc0 : (i < 'h71c) ? 8'he0 : (i < 'h71d) ? 8'hc0 :
(i < 'h720) ? 8'he0 : (i < 'h727) ? 8'hc0 : (i < 'h728) ? 8'he0 : (i < 'h72a) ? 8'hc0 :
(i < 'h73f) ? 8'he0 : (i < 'h740) ? 8'he7 : (i < 'h75f) ? 8'he0 : (i < 'h760) ? 8'he8 :
(i < 'h76e) ? 8'he0 : (i < 'h76f) ? 8'he8 : (i < 'h770) ? 8'hec : (i < 'h773) ? 8'he0 :
(i < 'h776) ? 8'he8 : (i < 'h777) ? 8'hec : (i < 'h778) ? 8'hee : (i < 'h77b) ? 8'hec :
(i < 'h77d) ? 8'hee : (i < 'h780) ? 8'hef : (i < 'h78d) ? 8'he0 : (i < 'h790) ? 8'hf0 :
(i < 'h792) ? 8'he0 : (i < 'h7af) ? 8'hf0 : (i < 'h7b0) ? 8'hf4 : (i < 'h7b7) ? 8'hf0 :
(i < 'h7b8) ? 8'hf4 : (i < 'h7b9) ? 8'hf0 : (i < 'h7bb) ? 8'hf4 : (i < 'h7bd) ? 8'hf6 :
(i < 'h7c0) ? 8'hf7 : (i < 'h7c3) ? 8'hf0 : (i < 'h7c4) ? 8'hf8 : (i < 'h7c5) ? 8'hf0 :
(i < 'h7db) ? 8'hf8 : (i < 'h7dd) ? 8'hfa : (i < 'h7e0) ? 8'hfb : (i < 'h7e1) ? 8'hf8 :
(i < 'h7ed) ? 8'hfc : (i < 'h7f0) ? 8'hfd : (i < 'h7f8) ? 8'hfe : 8'hff;
for(i = 0; i<4096; i=i+1) wave_ps_[i] =
(i < 'h07f) ? 8'h00 : (i < 'h080) ? 8'h03 : (i < 'h0bf) ? 8'h00 : (i < 'h0c0) ? 8'h01 :
(i < 'h0ff) ? 8'h00 : (i < 'h100) ? 8'h0f : (i < 'h17f) ? 8'h00 : (i < 'h180) ? 8'h07 :
(i < 'h1bf) ? 8'h00 : (i < 'h1c0) ? 8'h03 : (i < 'h1df) ? 8'h00 : (i < 'h1e0) ? 8'h01 :
(i < 'h1fd) ? 8'h00 : (i < 'h1ff) ? 8'h07 : (i < 'h200) ? 8'h1f : (i < 'h27f) ? 8'h00 :
(i < 'h280) ? 8'h03 : (i < 'h2bf) ? 8'h00 : (i < 'h2c0) ? 8'h03 : (i < 'h2df) ? 8'h00 :
(i < 'h2e0) ? 8'h01 : (i < 'h2fe) ? 8'h00 : (i < 'h2ff) ? 8'h01 : (i < 'h300) ? 8'h0f :
(i < 'h33f) ? 8'h00 : (i < 'h340) ? 8'h01 : (i < 'h37f) ? 8'h00 : (i < 'h380) ? 8'h17 :
(i < 'h3bf) ? 8'h00 : (i < 'h3c0) ? 8'h3b : (i < 'h3df) ? 8'h00 : (i < 'h3e0) ? 8'h3d :
(i < 'h3ef) ? 8'h00 : (i < 'h3f0) ? 8'h3e : (i < 'h3f7) ? 8'h00 : (i < 'h3f8) ? 8'h3f :
(i < 'h3f9) ? 8'h00 : (i < 'h3fa) ? 8'h0c : (i < 'h3fb) ? 8'h1c : (i < 'h3fc) ? 8'h3f :
(i < 'h3fd) ? 8'h1e : (i < 'h400) ? 8'h3f : (i < 'h47f) ? 8'h00 : (i < 'h480) ? 8'h03 :
(i < 'h4bf) ? 8'h00 : (i < 'h4c0) ? 8'h01 : (i < 'h4ff) ? 8'h00 : (i < 'h500) ? 8'h0f :
(i < 'h53f) ? 8'h00 : (i < 'h540) ? 8'h01 : (i < 'h57f) ? 8'h00 : (i < 'h580) ? 8'h07 :
(i < 'h5bf) ? 8'h00 : (i < 'h5c0) ? 8'h0b : (i < 'h5df) ? 8'h00 : (i < 'h5e0) ? 8'h0a :
(i < 'h5ef) ? 8'h00 : (i < 'h5f0) ? 8'h5e : (i < 'h5f7) ? 8'h00 : (i < 'h5f8) ? 8'h5f :
(i < 'h5fb) ? 8'h00 : (i < 'h5fc) ? 8'h5f : (i < 'h5fd) ? 8'h0c : (i < 'h600) ? 8'h5f :
(i < 'h63f) ? 8'h00 : (i < 'h640) ? 8'h01 : (i < 'h67f) ? 8'h00 : (i < 'h680) ? 8'h47 :
(i < 'h6bf) ? 8'h00 : (i < 'h6c0) ? 8'h43 : (i < 'h6df) ? 8'h00 : (i < 'h6e0) ? 8'h65 :
(i < 'h6ef) ? 8'h00 : (i < 'h6f0) ? 8'h6e : (i < 'h6f7) ? 8'h00 : (i < 'h6f8) ? 8'h6f :
(i < 'h6f9) ? 8'h00 : (i < 'h6fb) ? 8'h40 : (i < 'h6fc) ? 8'h6f : (i < 'h6fd) ? 8'h40 :
(i < 'h700) ? 8'h6f : (i < 'h73f) ? 8'h00 : (i < 'h740) ? 8'h63 : (i < 'h75e) ? 8'h00 :
(i < 'h75f) ? 8'h40 : (i < 'h760) ? 8'h61 : (i < 'h767) ? 8'h00 : (i < 'h768) ? 8'h40 :
(i < 'h76b) ? 8'h00 : (i < 'h76c) ? 8'h40 : (i < 'h76d) ? 8'h00 : (i < 'h76f) ? 8'h40 :
(i < 'h770) ? 8'h70 : (i < 'h772) ? 8'h00 : (i < 'h777) ? 8'h40 : (i < 'h778) ? 8'h70 :
(i < 'h779) ? 8'h40 : (i < 'h77b) ? 8'h60 : (i < 'h77c) ? 8'h77 : (i < 'h77d) ? 8'h60 :
(i < 'h780) ? 8'h77 : (i < 'h78f) ? 8'h00 : (i < 'h790) ? 8'h40 : (i < 'h796) ? 8'h00 :
(i < 'h797) ? 8'h40 : (i < 'h798) ? 8'h60 : (i < 'h799) ? 8'h00 : (i < 'h79b) ? 8'h40 :
(i < 'h79c) ? 8'h60 : (i < 'h79d) ? 8'h40 : (i < 'h79f) ? 8'h60 : (i < 'h7a0) ? 8'h79 :
(i < 'h7a1) ? 8'h00 : (i < 'h7a7) ? 8'h40 : (i < 'h7a8) ? 8'h60 : (i < 'h7ab) ? 8'h40 :
(i < 'h7af) ? 8'h60 : (i < 'h7b0) ? 8'h78 : (i < 'h7b1) ? 8'h40 : (i < 'h7b7) ? 8'h60 :
(i < 'h7b8) ? 8'h78 : (i < 'h7b9) ? 8'h60 : (i < 'h7bb) ? 8'h70 : (i < 'h7bc) ? 8'h78 :
(i < 'h7bd) ? 8'h70 : (i < 'h7be) ? 8'h79 : (i < 'h7c0) ? 8'h7b : (i < 'h7c7) ? 8'h60 :
(i < 'h7c8) ? 8'h70 : (i < 'h7cb) ? 8'h60 : (i < 'h7cc) ? 8'h70 : (i < 'h7cd) ? 8'h60 :
(i < 'h7cf) ? 8'h70 : (i < 'h7d0) ? 8'h7c : (i < 'h7d1) ? 8'h60 : (i < 'h7d7) ? 8'h70 :
(i < 'h7d8) ? 8'h7c : (i < 'h7d9) ? 8'h70 : (i < 'h7db) ? 8'h78 : (i < 'h7dc) ? 8'h7c :
(i < 'h7dd) ? 8'h78 : (i < 'h7df) ? 8'h7c : (i < 'h7e0) ? 8'h7d : (i < 'h7e1) ? 8'h70 :
(i < 'h7e7) ? 8'h78 : (i < 'h7e8) ? 8'h7c : (i < 'h7e9) ? 8'h78 : (i < 'h7eb) ? 8'h7c :
(i < 'h7ec) ? 8'h7e : (i < 'h7ed) ? 8'h7c : (i < 'h7f0) ? 8'h7e : (i < 'h7f3) ? 8'h7c :
(i < 'h7f5) ? 8'h7e : (i < 'h7f8) ? 8'h7f : (i < 'h7f9) ? 8'h7e : (i < 'h7ff) ? 8'h7f :
(i < 'h800) ? 8'hff : (i < 'h87f) ? 8'h00 : (i < 'h880) ? 8'h03 : (i < 'h8bf) ? 8'h00 :
(i < 'h8c0) ? 8'h01 : (i < 'h8ff) ? 8'h00 : (i < 'h900) ? 8'h8f : (i < 'h93f) ? 8'h00 :
(i < 'h940) ? 8'h01 : (i < 'h97f) ? 8'h00 : (i < 'h980) ? 8'h87 : (i < 'h9bf) ? 8'h00 :
(i < 'h9c0) ? 8'h83 : (i < 'h9de) ? 8'h00 : (i < 'h9df) ? 8'h80 : (i < 'h9e0) ? 8'h8d :
(i < 'h9e7) ? 8'h00 : (i < 'h9e8) ? 8'h80 : (i < 'h9eb) ? 8'h00 : (i < 'h9ec) ? 8'h80 :
(i < 'h9ed) ? 8'h00 : (i < 'h9ef) ? 8'h80 : (i < 'h9f0) ? 8'h8e : (i < 'h9f3) ? 8'h00 :
(i < 'h9f7) ? 8'h80 : (i < 'h9f8) ? 8'h8f : (i < 'h9fb) ? 8'h80 : (i < 'h9fc) ? 8'h9f :
(i < 'h9fd) ? 8'h80 : (i < 'ha00) ? 8'h9f : (i < 'ha3f) ? 8'h00 : (i < 'ha40) ? 8'h01 :
(i < 'ha6f) ? 8'h00 : (i < 'ha70) ? 8'h80 : (i < 'ha77) ? 8'h00 : (i < 'ha78) ? 8'h80 :
(i < 'ha7b) ? 8'h00 : (i < 'ha7c) ? 8'h80 : (i < 'ha7d) ? 8'h00 : (i < 'ha7f) ? 8'h80 :
(i < 'ha80) ? 8'h87 : (i < 'ha9f) ? 8'h00 : (i < 'haa0) ? 8'h80 : (i < 'haaf) ? 8'h00 :
(i < 'hab0) ? 8'h80 : (i < 'hab7) ? 8'h00 : (i < 'hab8) ? 8'h80 : (i < 'habb) ? 8'h00 :
(i < 'habf) ? 8'h80 : (i < 'hac0) ? 8'h83 : (i < 'hacf) ? 8'h00 : (i < 'had0) ? 8'h80 :
(i < 'had5) ? 8'h00 : (i < 'had8) ? 8'h80 : (i < 'had9) ? 8'h00 : (i < 'hadf) ? 8'h80 :
(i < 'hae0) ? 8'h81 : (i < 'haef) ? 8'h80 : (i < 'haf0) ? 8'h84 : (i < 'haf7) ? 8'h80 :
(i < 'haf8) ? 8'h87 : (i < 'hafb) ? 8'h80 : (i < 'hafc) ? 8'h87 : (i < 'hafd) ? 8'h80 :
(i < 'hafe) ? 8'h8f : (i < 'hb00) ? 8'haf : (i < 'hb0f) ? 8'h00 : (i < 'hb10) ? 8'h80 :
(i < 'hb17) ? 8'h00 : (i < 'hb18) ? 8'h80 : (i < 'hb1b) ? 8'h00 : (i < 'hb20) ? 8'h80 :
(i < 'hb23) ? 8'h00 : (i < 'hb24) ? 8'h80 : (i < 'hb26) ? 8'h00 : (i < 'hb28) ? 8'h80 :
(i < 'hb29) ? 8'h00 : (i < 'hb3f) ? 8'h80 : (i < 'hb40) ? 8'h83 : (i < 'hb5f) ? 8'h80 :
(i < 'hb60) ? 8'h81 : (i < 'hb6f) ? 8'h80 : (i < 'hb70) ? 8'ha0 : (i < 'hb77) ? 8'h80 :
(i < 'hb78) ? 8'ha0 : (i < 'hb7b) ? 8'h80 : (i < 'hb7c) ? 8'ha0 : (i < 'hb7d) ? 8'h80 :
(i < 'hb7e) ? 8'ha3 : (i < 'hb80) ? 8'hb7 : (i < 'hb9f) ? 8'h80 : (i < 'hba0) ? 8'hb1 :
(i < 'hbaf) ? 8'h80 : (i < 'hbb0) ? 8'hb0 : (i < 'hbb7) ? 8'h80 : (i < 'hbb8) ? 8'hb0 :
(i < 'hbb9) ? 8'h80 : (i < 'hbbb) ? 8'ha0 : (i < 'hbbc) ? 8'hb0 : (i < 'hbbd) ? 8'ha0 :
(i < 'hbbe) ? 8'hb8 : (i < 'hbbf) ? 8'hb9 : (i < 'hbc0) ? 8'hbb : (i < 'hbc7) ? 8'h80 :
(i < 'hbc8) ? 8'ha0 : (i < 'hbcb) ? 8'h80 : (i < 'hbcc) ? 8'ha0 : (i < 'hbcd) ? 8'h80 :
(i < 'hbcf) ? 8'ha0 : (i < 'hbd0) ? 8'hb8 : (i < 'hbd1) ? 8'h80 : (i < 'hbd7) ? 8'ha0 :
(i < 'hbd8) ? 8'hb8 : (i < 'hbd9) ? 8'ha0 : (i < 'hbdb) ? 8'hb0 : (i < 'hbdc) ? 8'hb8 :
(i < 'hbdd) ? 8'hb0 : (i < 'hbdf) ? 8'hbc : (i < 'hbe0) ? 8'hbd : (i < 'hbe1) ? 8'ha0 :
(i < 'hbe5) ? 8'hb0 : (i < 'hbe7) ? 8'hb8 : (i < 'hbe8) ? 8'hbc : (i < 'hbe9) ? 8'hb0 :
(i < 'hbeb) ? 8'hb8 : (i < 'hbec) ? 8'hbc : (i < 'hbed) ? 8'hb8 : (i < 'hbee) ? 8'hbc :
(i < 'hbf0) ? 8'hbe : (i < 'hbf1) ? 8'hb8 : (i < 'hbf3) ? 8'hbc : (i < 'hbf4) ? 8'hbe :
(i < 'hbf5) ? 8'hbc : (i < 'hbf7) ? 8'hbe : (i < 'hbf8) ? 8'hbf : (i < 'hbf9) ? 8'hbe :
(i < 'hc00) ? 8'hbf : (i < 'hc03) ? 8'h00 : (i < 'hc04) ? 8'h80 : (i < 'hc07) ? 8'h00 :
(i < 'hc08) ? 8'h80 : (i < 'hc0b) ? 8'h00 : (i < 'hc0c) ? 8'h80 : (i < 'hc0f) ? 8'h00 :
(i < 'hc10) ? 8'h80 : (i < 'hc11) ? 8'h00 : (i < 'hc18) ? 8'h80 : (i < 'hc19) ? 8'h00 :
(i < 'hc3f) ? 8'h80 : (i < 'hc40) ? 8'h81 : (i < 'hc7f) ? 8'h80 : (i < 'hc80) ? 8'hc7 :
(i < 'hcbe) ? 8'h80 : (i < 'hcbf) ? 8'hc0 : (i < 'hcc0) ? 8'hc3 : (i < 'hccf) ? 8'h80 :
(i < 'hcd0) ? 8'hc0 : (i < 'hcd7) ? 8'h80 : (i < 'hcd8) ? 8'hc0 : (i < 'hcdb) ? 8'h80 :
(i < 'hcdc) ? 8'hc0 : (i < 'hcdd) ? 8'h80 : (i < 'hcdf) ? 8'hc0 : (i < 'hce0) ? 8'hc1 :
(i < 'hce7) ? 8'h80 : (i < 'hce8) ? 8'hc0 : (i < 'hceb) ? 8'h80 : (i < 'hcf7) ? 8'hc0 :
(i < 'hcf8) ? 8'hc7 : (i < 'hcfb) ? 8'hc0 : (i < 'hcfc) ? 8'hc7 : (i < 'hcfd) ? 8'hc0 :
(i < 'hd00) ? 8'hcf : (i < 'hd1f) ? 8'h80 : (i < 'hd20) ? 8'hc0 : (i < 'hd2f) ? 8'h80 :
(i < 'hd30) ? 8'hc0 : (i < 'hd36) ? 8'h80 : (i < 'hd38) ? 8'hc0 : (i < 'hd39) ? 8'h80 :
(i < 'hd3f) ? 8'hc0 : (i < 'hd40) ? 8'hc3 : (i < 'hd47) ? 8'h80 : (i < 'hd48) ? 8'hc0 :
(i < 'hd4b) ? 8'h80 : (i < 'hd4c) ? 8'hc0 : (i < 'hd4d) ? 8'h80 : (i < 'hd50) ? 8'hc0 :
(i < 'hd51) ? 8'h80 : (i < 'hd5f) ? 8'hc0 : (i < 'hd60) ? 8'hc1 : (i < 'hd7d) ? 8'hc0 :
(i < 'hd7e) ? 8'hc1 : (i < 'hd7f) ? 8'hc7 : (i < 'hd80) ? 8'hd7 : (i < 'hdaf) ? 8'hc0 :
(i < 'hdb0) ? 8'hd0 : (i < 'hdb7) ? 8'hc0 : (i < 'hdb8) ? 8'hd0 : (i < 'hdbb) ? 8'hc0 :
(i < 'hdbc) ? 8'hd0 : (i < 'hdbd) ? 8'hc0 : (i < 'hdbe) ? 8'hd0 : (i < 'hdbf) ? 8'hd8 :
(i < 'hdc0) ? 8'hdb : (i < 'hdcf) ? 8'hc0 : (i < 'hdd0) ? 8'hd8 : (i < 'hdd7) ? 8'hc0 :
(i < 'hdd8) ? 8'hd8 : (i < 'hddb) ? 8'hc0 : (i < 'hddc) ? 8'hd8 : (i < 'hddd) ? 8'hd0 :
(i < 'hddf) ? 8'hd8 : (i < 'hde0) ? 8'hdd : (i < 'hde3) ? 8'hc0 : (i < 'hde4) ? 8'hd0 :
(i < 'hde5) ? 8'hc0 : (i < 'hde7) ? 8'hd0 : (i < 'hde8) ? 8'hdc : (i < 'hde9) ? 8'hd0 :
(i < 'hdeb) ? 8'hd8 : (i < 'hdec) ? 8'hdc : (i < 'hded) ? 8'hd8 : (i < 'hdef) ? 8'hdc :
(i < 'hdf0) ? 8'hde : (i < 'hdf1) ? 8'hd8 : (i < 'hdf3) ? 8'hdc : (i < 'hdf4) ? 8'hde :
(i < 'hdf5) ? 8'hdc : (i < 'hdf7) ? 8'hde : (i < 'hdf8) ? 8'hdf : (i < 'hdf9) ? 8'hde :
(i < 'he00) ? 8'hdf : (i < 'he3f) ? 8'hc0 : (i < 'he40) ? 8'he3 : (i < 'he57) ? 8'hc0 :
(i < 'he58) ? 8'he0 : (i < 'he5b) ? 8'hc0 : (i < 'he5c) ? 8'he0 : (i < 'he5d) ? 8'hc0 :
(i < 'he5f) ? 8'he0 : (i < 'he60) ? 8'he1 : (i < 'he67) ? 8'hc0 : (i < 'he68) ? 8'he0 :
(i < 'he6b) ? 8'hc0 : (i < 'he70) ? 8'he0 : (i < 'he71) ? 8'hc0 : (i < 'he7d) ? 8'he0 :
(i < 'he7e) ? 8'he1 : (i < 'he7f) ? 8'he3 : (i < 'he80) ? 8'he7 : (i < 'he87) ? 8'hc0 :
(i < 'he88) ? 8'he0 : (i < 'he8b) ? 8'hc0 : (i < 'he8c) ? 8'he0 : (i < 'he8d) ? 8'hc0 :
(i < 'he90) ? 8'he0 : (i < 'he93) ? 8'hc0 : (i < 'he94) ? 8'he0 : (i < 'he95) ? 8'hc0 :
(i < 'hebf) ? 8'he0 : (i < 'hec0) ? 8'heb : (i < 'hedb) ? 8'he0 : (i < 'hedc) ? 8'he8 :
(i < 'hedd) ? 8'he0 : (i < 'hedf) ? 8'he8 : (i < 'hee0) ? 8'hed : (i < 'hee7) ? 8'he0 :
(i < 'hee8) ? 8'hec : (i < 'heeb) ? 8'he0 : (i < 'heec) ? 8'hec : (i < 'heed) ? 8'he8 :
(i < 'heef) ? 8'hec : (i < 'hef0) ? 8'hee : (i < 'hef3) ? 8'he8 : (i < 'hef5) ? 8'hec :
(i < 'hef7) ? 8'hee : (i < 'hef8) ? 8'hef : (i < 'hef9) ? 8'hec : (i < 'hf00) ? 8'hef :
(i < 'hf1f) ? 8'he0 : (i < 'hf20) ? 8'hf0 : (i < 'hf27) ? 8'he0 : (i < 'hf28) ? 8'hf0 :
(i < 'hf2b) ? 8'he0 : (i < 'hf2c) ? 8'hf0 : (i < 'hf2d) ? 8'he0 : (i < 'hf30) ? 8'hf0 :
(i < 'hf33) ? 8'he0 : (i < 'hf3f) ? 8'hf0 : (i < 'hf40) ? 8'hf3 : (i < 'hf43) ? 8'he0 :
(i < 'hf5f) ? 8'hf0 : (i < 'hf60) ? 8'hf5 : (i < 'hf6d) ? 8'hf0 : (i < 'hf6f) ? 8'hf4 :
(i < 'hf70) ? 8'hf6 : (i < 'hf73) ? 8'hf0 : (i < 'hf74) ? 8'hf4 : (i < 'hf75) ? 8'hf0 :
(i < 'hf76) ? 8'hf4 : (i < 'hf77) ? 8'hf6 : (i < 'hf78) ? 8'hf7 : (i < 'hf79) ? 8'hf4 :
(i < 'hf7b) ? 8'hf6 : (i < 'hf80) ? 8'hf7 : (i < 'hf87) ? 8'hf0 : (i < 'hf88) ? 8'hf8 :
(i < 'hf8d) ? 8'hf0 : (i < 'hf90) ? 8'hf8 : (i < 'hf93) ? 8'hf0 : (i < 'hf94) ? 8'hf8 :
(i < 'hf95) ? 8'hf0 : (i < 'hf9f) ? 8'hf8 : (i < 'hfa0) ? 8'hf9 : (i < 'hfaf) ? 8'hf8 :
(i < 'hfb0) ? 8'hfa : (i < 'hfb7) ? 8'hf8 : (i < 'hfb8) ? 8'hfb : (i < 'hfb9) ? 8'hf8 :
(i < 'hfbb) ? 8'hfa : (i < 'hfc0) ? 8'hfb : (i < 'hfc3) ? 8'hf8 : (i < 'hfc4) ? 8'hfc :
(i < 'hfc5) ? 8'hf8 : (i < 'hfd7) ? 8'hfc : (i < 'hfd8) ? 8'hfd : (i < 'hfdb) ? 8'hfc :
(i < 'hfe0) ? 8'hfd : (i < 'hfe2) ? 8'hfc : (i < 'hff0) ? 8'hfe : 8'hff;
for(i = 0; i<4096; i=i+1) wave_pst[i] =
(i < 'h3ff) ? 8'h00 : (i < 'h400) ? 8'h1f : (i < 'h7ee) ? 8'h00 : (i < 'h7ef) ? 8'h20 :
(i < 'h7f0) ? 8'h70 : (i < 'h7f1) ? 8'h60 : (i < 'h7f2) ? 8'h20 : (i < 'h7f7) ? 8'h70 :
(i < 'h7fa) ? 8'h78 : (i < 'h7fc) ? 8'h7c : (i < 'h7fe) ? 8'h7e : (i < 'h800) ? 8'h7f :
(i < 'hbfd) ? 8'h00 : (i < 'hbfe) ? 8'h08 : (i < 'hbff) ? 8'h1e : (i < 'hc00) ? 8'h3f :
(i < 'hdf7) ? 8'h00 : (i < 'hdfe) ? 8'h80 : (i < 'hdff) ? 8'h8c : (i < 'he00) ? 8'h9f :
(i < 'he3e) ? 8'h00 : (i < 'he40) ? 8'h80 : (i < 'he5e) ? 8'h00 : (i < 'he60) ? 8'h80 :
(i < 'he66) ? 8'h00 : (i < 'he67) ? 8'h80 : (i < 'he6a) ? 8'h00 : (i < 'he80) ? 8'h80 :
(i < 'he82) ? 8'h00 : (i < 'he83) ? 8'h80 : (i < 'he85) ? 8'h00 : (i < 'he89) ? 8'h80 :
(i < 'he8a) ? 8'h00 : (i < 'heee) ? 8'h80 : (i < 'heff) ? 8'hc0 : (i < 'hf00) ? 8'hcf :
(i < 'hf6f) ? 8'hc0 : (i < 'hf70) ? 8'he0 : (i < 'hf74) ? 8'hc0 : (i < 'hf7f) ? 8'he0 :
(i < 'hf80) ? 8'he3 : (i < 'hfb6) ? 8'he0 : (i < 'hfda) ? 8'hf0 : (i < 'hfeb) ? 8'hf8 :
(i < 'hff5) ? 8'hfc : (i < 'hff9) ? 8'hfe : 8'hff;
end
endmodule

View File

@@ -1,29 +1,130 @@
module sigma_delta_dac #(parameter MSBI=14, parameter INV=1'b1)
(
output reg DACout = INV, //Average Output feeding analog lowpass
input [MSBI:0] DACin, //DAC input (excess 2**MSBI)
input CLK,
input RESET
// sigmadelta.v
// two channel second order sigma delta dac
// taken from Minimig
// audio data processing
// stereo sigma/delta bitstream modulator
module sigma_delta_dac (
input clk, // bus clock
input [14:0] ldatasum, // left channel data
input [14:0] rdatasum, // right channel data
output reg aleft=0, // left bitstream output
output reg aright=0 // right bitsteam output
);
reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder
reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder
reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder
reg [MSBI+2:0] DeltaB; //B input of Delta Adder
//--------------------------------------------------------------------------------------
always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1);
always @(*) DeltaAdder = DACin + DeltaB;
always @(*) SigmaAdder = DeltaAdder + SigmaLatch;
// local signals
localparam DW = 15;
localparam CW = 2;
localparam RW = 4;
localparam A1W = 2;
localparam A2W = 5;
always @(posedge CLK or posedge RESET) begin
if(RESET) begin
SigmaLatch <= 1'b1 << (MSBI+1);
DACout <= INV;
end else begin
SigmaLatch <= SigmaAdder;
DACout <= SigmaLatch[MSBI+2] ^ INV;
end
wire [DW+2+0 -1:0] sd_l_er0, sd_r_er0;
reg [DW+2+0 -1:0] sd_l_er0_prev=0, sd_r_er0_prev=0;
wire [DW+A1W+2-1:0] sd_l_aca1, sd_r_aca1;
wire [DW+A2W+2-1:0] sd_l_aca2, sd_r_aca2;
reg [DW+A1W+2-1:0] sd_l_ac1=0, sd_r_ac1=0;
reg [DW+A2W+2-1:0] sd_l_ac2=0, sd_r_ac2=0;
wire [DW+A2W+3-1:0] sd_l_quant, sd_r_quant;
// LPF noise LFSR
reg [24-1:0] seed1 = 24'h654321;
reg [19-1:0] seed2 = 19'h12345;
reg [24-1:0] seed_sum=0, seed_prev=0, seed_out=0;
always @ (posedge clk) begin
if (&seed1)
seed1 <= #1 24'h654321;
else
seed1 <= #1 {seed1[22:0], ~(seed1[23] ^ seed1[22] ^ seed1[21] ^ seed1[16])};
end
always @ (posedge clk) begin
if (&seed2)
seed2 <= #1 19'h12345;
else
seed2 <= #1 {seed2[17:0], ~(seed2[18] ^ seed2[17] ^ seed2[16] ^ seed2[13] ^ seed2[0])};
end
always @ (posedge clk) begin
seed_sum <= #1 seed1 + {5'b0, seed2};
seed_prev <= #1 seed_sum;
seed_out <= #1 seed_sum - seed_prev;
end
endmodule
// linear interpolate
localparam ID=4; // counter size, also 2^ID = interpolation rate
reg [ID+0-1:0] int_cnt = 0;
always @ (posedge clk) int_cnt <= #1 int_cnt + 'd1;
reg [DW+0-1:0] ldata_cur=0, ldata_prev=0;
reg [DW+0-1:0] rdata_cur=0, rdata_prev=0;
wire [DW+1-1:0] ldata_step, rdata_step;
reg [DW+ID-1:0] ldata_int=0, rdata_int=0;
wire [DW+0-1:0] ldata_int_out, rdata_int_out;
assign ldata_step = {ldata_cur[DW-1], ldata_cur} - {ldata_prev[DW-1], ldata_prev}; // signed subtract
assign rdata_step = {rdata_cur[DW-1], rdata_cur} - {rdata_prev[DW-1], rdata_prev}; // signed subtract
always @ (posedge clk) begin
if (~|int_cnt) begin
ldata_prev <= #1 ldata_cur;
ldata_cur <= #1 ldatasum; //{~ldatasum[DW-1], ldatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
rdata_prev <= #1 rdata_cur;
rdata_cur <= #1 rdatasum; //{~rdatasum[DW-1], rdatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
ldata_int <= #1 {ldata_cur[DW-1], ldata_cur, {ID{1'b0}}};
rdata_int <= #1 {rdata_cur[DW-1], rdata_cur, {ID{1'b0}}};
end else begin
ldata_int <= #1 ldata_int + {{ID{ldata_step[DW+1-1]}}, ldata_step};
rdata_int <= #1 rdata_int + {{ID{rdata_step[DW+1-1]}}, rdata_step};
end
end
assign ldata_int_out = ldata_int[DW+ID-1:ID];
assign rdata_int_out = rdata_int[DW+ID-1:ID];
// input gain x3
wire [DW+2-1:0] ldata_gain, rdata_gain;
assign ldata_gain = {ldata_int_out[DW-1], ldata_int_out, 1'b0} + {{(2){ldata_int_out[DW-1]}}, ldata_int_out};
assign rdata_gain = {rdata_int_out[DW-1], rdata_int_out, 1'b0} + {{(2){rdata_int_out[DW-1]}}, rdata_int_out};
/*
// random dither to 15 bits
reg [DW-1:0] ldata=0, rdata=0;
always @ (posedge clk) begin
ldata <= #1 ldata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
rdata <= #1 rdata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
end
*/
// accumulator adders
assign sd_l_aca1 = {{(A1W){ldata_gain[DW+2-1]}}, ldata_gain} - {{(A1W){sd_l_er0[DW+2-1]}}, sd_l_er0} + sd_l_ac1;
assign sd_r_aca1 = {{(A1W){rdata_gain[DW+2-1]}}, rdata_gain} - {{(A1W){sd_r_er0[DW+2-1]}}, sd_r_er0} + sd_r_ac1;
assign sd_l_aca2 = {{(A2W-A1W){sd_l_aca1[DW+A1W+2-1]}}, sd_l_aca1} - {{(A2W){sd_l_er0[DW+2-1]}}, sd_l_er0} - {{(A2W+1){sd_l_er0_prev[DW+2-1]}}, sd_l_er0_prev[DW+2-1:1]} + sd_l_ac2;
assign sd_r_aca2 = {{(A2W-A1W){sd_r_aca1[DW+A1W+2-1]}}, sd_r_aca1} - {{(A2W){sd_r_er0[DW+2-1]}}, sd_r_er0} - {{(A2W+1){sd_r_er0_prev[DW+2-1]}}, sd_r_er0_prev[DW+2-1:1]} + sd_r_ac2;
// accumulators
always @ (posedge clk) begin
sd_l_ac1 <= #1 sd_l_aca1;
sd_r_ac1 <= #1 sd_r_aca1;
sd_l_ac2 <= #1 sd_l_aca2;
sd_r_ac2 <= #1 sd_r_aca2;
end
// value for quantizaton
assign sd_l_quant = {sd_l_ac2[DW+A2W+2-1], sd_l_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
assign sd_r_quant = {sd_r_ac2[DW+A2W+2-1], sd_r_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
// error feedback
assign sd_l_er0 = sd_l_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
assign sd_r_er0 = sd_r_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
always @ (posedge clk) begin
sd_l_er0_prev <= #1 (&sd_l_er0) ? sd_l_er0 : sd_l_er0+1;
sd_r_er0_prev <= #1 (&sd_r_er0) ? sd_r_er0 : sd_r_er0+1;
end
// output
always @ (posedge clk) begin
aleft <= #1 (~|ldata_gain) ? ~aleft : ~sd_l_er0[DW+2-1];
aright <= #1 (~|rdata_gain) ? ~aright : ~sd_r_er0[DW+2-1];
end
endmodule

View File

@@ -1,20 +0,0 @@
// 64 byte buffer for loading files
// used to interrogate file type
// L.C.Ashmore 17
//
//
module header_buffer
(
inout reg [7:0] header_buff [0:63]
);
integer i;
initial begin
for (i = 0; i < 64; i = i +1)
header_buff [i] = 0;
end
endmodule

View File

@@ -1,46 +0,0 @@
// memory block transfer routine
// L.C.Ashmore feb17
//
// PRG T64 CRT TAP files load to intermediate buffer 0x200000 (2m)
//
// this routine reads 1st 16bytes to determine file type then either:
// 1, if CRT or TAP move to 0x100000 (1m) and sets cartridge or tap attached flags
// 2, if PRG or T64 moves directly into c64 memory map (injection)
// T64 format pain in the arse so only basic function !!
module block_transfer
(
input clk32,
input [31:0] addr_total_size,
input sdram_we,
input sdram_data_out,
output cart_attached,
output reg [24:0] sdram_read_addr,
output reg [24:0] sdram_write_addr,
inout reg [7:0] sdram_data
);
localparam buffer_address2m = 'h200000;
localparam buffer_address1m = 'h100000;
reg [24:0] block_addr;
//reg [24:0] sdram_read_addr;
//reg [24:0] sdram_write_addr;
//reg [7:0] sdram_data;
reg transfer_active;
reg read_flag;
always @(negedge clk32)
begin
if (sdram_we == 1 && transfer_active && !read_flag) //sdram in read cycle - not yet read
begin
sdram_read_addr <= block_addr + buffer_address2m;
sdram_data <= sdram_data_out;
read_flag = 1;
end
if (sdram_we == 0 && read_flag)
begin
sdram_write_addr <= block_addr +buffer_address1m;
end
end
endmodule