1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-05 23:54:41 +00:00

Merge pull request #57 from gyurco/c16

C16
This commit is contained in:
Till Harbaum
2018-08-29 10:23:03 +02:00
committed by GitHub
26 changed files with 21374 additions and 1901 deletions

View File

@@ -0,0 +1,395 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
--use work.platform_pkg.all;
--use work.project_pkg.all;
--
-- Model 1541B
--
entity c1541_logic is
generic
(
DEVICE_SELECT : std_logic_vector(1 downto 0)
);
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_oe : out std_logic;
sb_atn_in : 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 data to write
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
dbg_adr_fetch : out std_logic_vector(15 downto 0); -- dbg DAR
dbg_cpu_irq : out std_logic -- dbg DAR
);
end c1541_logic;
architecture SYN of c1541_logic is
-- clocks, reset
signal reset_n : std_logic;
signal clk_4M_en : std_logic;
signal p2_h : std_logic;
signal clk_1M_pulse : std_logic;
-- cpu signals
signal cpu_a : std_logic_vector(23 downto 0);
signal cpu_di : std_logic_vector(7 downto 0);
signal cpu_do : std_logic_vector(7 downto 0);
signal cpu_rw_n : std_logic;
signal cpu_irq_n : std_logic;
signal cpu_so_n : std_logic;
signal cpu_sync : std_logic; -- DAR
-- 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_do_oe_n : std_logic;
signal uc1_cs1 : std_logic;
signal uc1_cs2_n : std_logic;
signal uc1_irq_n : std_logic;
signal uc1_ca1_i : std_logic;
signal uc1_pa_i : std_logic_vector(7 downto 0);
signal uc1_pb_i : std_logic_vector(7 downto 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_do_oe_n : std_logic;
signal uc3_cs1 : std_logic;
signal uc3_cs2_n : 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
begin
reset_n <= not reset;
process (clk_32M, reset)
variable count : std_logic_vector(8 downto 0) := (others => '0');
alias hcnt : std_logic_vector(1 downto 0) is count(4 downto 3);
begin
if rising_edge(clk_32M) then
-- generate 1MHz pulse
clk_1M_pulse <= '0';
--if count(4 downto 0) = "00111" then
if count(4 downto 0) = "01000" then
clk_1M_pulse <= '1';
end if;
if count = "000100000" then -- DAR divide by 33 (otherwise real c64 miss EOI acknowledge)
count := (others => '0'); -- DAR
else -- DAR
count := std_logic_vector(unsigned(count) + 1);
end if; -- DAR
end if;
p2_h <= not hcnt(1);
-- for original m6522 design that requires a real clock
-- clk_4M_en <= not count(2);
-- for version 002 with clock enable
if count(2 downto 0) = "111" then
clk_4M_en <= '1';
else
clk_4M_en <= '0';
end if;
end process;
-- decode logic
-- RAM $0000-$07FF (2KB)
ram_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "00000-----------") else '0';
-- UC1 (VIA6522) $1800-$180F
uc1_cs2_n <= '0' when STD_MATCH(cpu_a(15 downto 0), "000110000000----") else '1';
-- UC3 (VIA6522) $1C00-$1C0F
uc3_cs2_n <= '0' when STD_MATCH(cpu_a(15 downto 0), "000111000000----") else '1';
-- ROM $C000-$FFFF (16KB)
rom_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "11--------------") else '0';
-- qualified write signals
ram_wr <= '1' when ram_cs = '1' and cpu_rw_n = '0' else '0';
--
-- hook up UC1 ports
--
uc1_cs1 <= cpu_a(11);
--uc1_cs2_n: see decode logic above
-- CA1
--uc1_ca1_i <= not sb_atn_in; -- DAR comment : synched with clk_4M_en see below
-- PA
uc1_pa_i(0) <= tr00_sense_n;
uc1_pa_i(7 downto 1) <= (others => '0'); -- NC
-- PB
uc1_pb_i(0) <= '1' when sb_data_in = '0' else
'1' when (uc1_pb_o(1) = '1' and uc1_pb_oe_n(1) = '0') else -- DAR comment : external OR wired
'1' when atn = '1' else -- DAR comment : external OR wired
'0';
sb_data_oe <= '1' when (uc1_pb_o(1) = '1' and uc1_pb_oe_n(1) = '0') else
'1' when atn = '1' else
'0';
uc1_pb_i(2) <= '1' when sb_clk_in = '0' else
'1' when (uc1_pb_o(3) = '1' and uc1_pb_oe_n(3) = '0') else -- DAR comment : external OR wired
'0';
sb_clk_oe <= '1' when (uc1_pb_o(3) = '1' and uc1_pb_oe_n(3) = '0') else '0';
atna <= uc1_pb_o(4); -- when uc1_pc_oe = '1'
uc1_pb_i(6 downto 5) <= DEVICE_SELECT xor ds; -- allows override
uc1_pb_i(7) <= not sb_atn_in;
--
-- hook up UC3 ports
--
uc3_cs1 <= cpu_a(11);
--uc3_cs2_n: see decode logic above
-- CA1
uc3_ca1_i <= cpu_so_n; -- byte ready gated with soe
-- CA2
soe <= uc3_ca2_o or uc3_ca2_oe_n;
-- PA
uc3_pa_i <= di;
do <= uc3_pa_o or uc3_pa_oe_n;
-- CB2
mode <= uc3_cb2_o or uc3_cb2_oe_n;
-- PB
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_cs1 = '1' and uc1_cs2_n = '0') else
uc3_do when (uc3_cs1 = '1' and uc3_cs2_n = '0') 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);
-- external connections
-- ATN never driven by the 1541
sb_atn_oe <= '0';
-- DAR
process (clk_32M)
begin
if rising_edge(clk_32M) then
if clk_4M_en = '1' then
uc1_ca1_i <= not sb_atn_in; -- DAR sample external atn to ensure not missing edge within VIA
end if;
end if;
end process;
process (clk_32M, cpu_sync)
begin
if rising_edge(clk_32M) then
if cpu_sync = '1' then
dbg_adr_fetch <= cpu_a(15 downto 0);
end if;
end if;
end process;
dbg_cpu_irq <= cpu_irq_n;
-- DAR
cpu_inst : entity work.T65
port map
(
Mode => "00", -- 6502
Res_n => reset_n,
Enable => clk_1M_pulse,
Clk => clk_32M,
Rdy => '1',
Abort_n => '1',
IRQ_n => cpu_irq_n,
NMI_n => '1',
SO_n => cpu_so_n,
R_W_n => cpu_rw_n,
Sync => cpu_sync, -- open -- DAR
EF => open,
MF => open,
XF => open,
ML_n => open,
VP_n => open,
VDA => open,
VPA => open,
A => cpu_a,
DI => cpu_di,
DO => cpu_do
);
rom_inst : entity work.sprom
generic map
(
-- init_file => "../roms/JiffyDOS_C1541.hex", -- DAR tested OK
-- init_file => "../roms/25196802.hex",
-- init_file => "../roms/25196801.hex",
init_file => "../roms/325302-1_901229-03.hex",
-- init_file => "../roms/1541_c000_01_and_e000_06aa.hex", -- DAR tested OK
numwords_a => 16384,
widthad_a => 14
)
port map
(
clock => clk_32M,
address => cpu_a(13 downto 0),
q => rom_do
);
ram_inst : entity work.spram
generic map
(
numwords_a => 2048,
widthad_a => 11
)
port map
(
clock => clk_32M,
address => cpu_a(10 downto 0),
wren => ram_wr,
data => cpu_do,
q => ram_do
);
uc1_via6522_inst : entity work.M6522
port map
(
I_RS => cpu_a(3 downto 0),
I_DATA => cpu_do,
O_DATA => uc1_do,
O_DATA_OE_L => uc1_do_oe_n,
I_RW_L => cpu_rw_n,
I_CS1 => uc1_cs1,
I_CS2_L => uc1_cs2_n,
O_IRQ_L => uc1_irq_n,
-- port a
I_CA1 => uc1_ca1_i,
I_CA2 => '0',
O_CA2 => open,
O_CA2_OE_L => open,
I_PA => uc1_pa_i,
O_PA => open,
O_PA_OE_L => open,
-- port b
I_CB1 => '0',
O_CB1 => open,
O_CB1_OE_L => open,
I_CB2 => '0',
O_CB2 => open,
O_CB2_OE_L => open,
I_PB => uc1_pb_i,
O_PB => uc1_pb_o,
O_PB_OE_L => uc1_pb_oe_n,
RESET_L => reset_n,
CLK => clk_32M,
I_P2_H => p2_h, -- high for phase 2 clock ____----__
ENA_4 => clk_4M_en -- 4x system clock (4HZ) _-_-_-_-_-
);
uc3_via6522_inst : entity work.M6522
port map
(
I_RS => cpu_a(3 downto 0),
I_DATA => cpu_do,
O_DATA => uc3_do,
O_DATA_OE_L => uc3_do_oe_n,
I_RW_L => cpu_rw_n,
I_CS1 => cpu_a(11),
I_CS2_L => uc3_cs2_n,
O_IRQ_L => uc3_irq_n,
-- port a
I_CA1 => uc3_ca1_i,
I_CA2 => '0',
O_CA2 => uc3_ca2_o,
O_CA2_OE_L => uc3_ca2_oe_n,
I_PA => uc3_pa_i,
O_PA => uc3_pa_o,
O_PA_OE_L => uc3_pa_oe_n,
-- port b
I_CB1 => '0',
O_CB1 => open,
O_CB1_OE_L => open,
I_CB2 => '0',
O_CB2 => uc3_cb2_o,
O_CB2_OE_L => uc3_cb2_oe_n,
I_PB => uc3_pb_i,
O_PB => uc3_pb_o,
O_PB_OE_L => uc3_pb_oe_n,
RESET_L => reset_n,
CLK => clk_32M,
I_P2_H => p2_h, -- high for phase 2 clock ____----__
ENA_4 => clk_4M_en -- 4x system clock (4HZ) _-_-_-_-_-
);
end SYN;

View File

@@ -0,0 +1,376 @@
---------------------------------------------------------------------------------
-- Commodore 1541 to SD card (read/write) by Dar (darfpga@aol.fr) 24-May-2017
-- http://darfpga.blogspot.fr
--
-- c1541_sd reads D64 data from raw SD card, produces GCR data, feeds c1541_logic
-- Raw SD data : each D64 image must start on 256KB boundaries
-- disk_num allow to select D64 image
--
-- c1541_logic from : Mark McDougall
-- spi_controller from : Michel Stempin, Stephen A. Edwards
-- via6522 from : Arnim Laeuger, Mark McDougall, MikeJ
-- T65 from : Daniel Wallner, MikeJ, ehenciak
--
-- 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)
-- spi_controller modified for : sector start and size adapted + busy signal
-- via6522 modified for : no modification
--
--
-- Input clk 32MHz and 18MHz (18MHz could be replaced with 32/2 if needed)
--
---------------------------------------------------------------------------------
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;
-- clk_spi_ctrlr : in std_logic;
reset : in std_logic;
disk_num : in std_logic_vector(9 downto 0);
disk_change : in std_logic;
iec_atn_i : in std_logic;
iec_data_i : in std_logic;
iec_clk_i : in std_logic;
iec_atn_o : out 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;
dbg_track_num_dbl : out std_logic_vector(6 downto 0);
dbg_sd_busy : out std_logic;
dbg_sd_state : out std_logic_vector(7 downto 0);
dbg_read_sector : out std_logic_vector(4 downto 0);
dbg_mtr : out std_logic;
dbg_act : out std_logic
);
end c1541_sd;
architecture struct of c1541_sd is
signal spi_ram_addr : std_logic_vector(12 downto 0);
signal spi_ram_di : std_logic_vector( 7 downto 0);
signal spi_ram_we : std_logic;
signal ram_addr : std_logic_vector(12 downto 0);
signal ram_di : std_logic_vector( 7 downto 0);
signal ram_do : std_logic_vector( 7 downto 0);
signal ram_we : std_logic;
signal floppy_ram_addr : std_logic_vector(12 downto 0);
signal floppy_ram_di : std_logic_vector( 7 downto 0);
signal floppy_ram_we : std_logic;
signal c1541_logic_din : std_logic_vector(7 downto 0); -- data read
signal c1541_logic_dout : std_logic_vector(7 downto 0); -- data to write
signal mode : std_logic; -- read/write
signal mode_r : 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 mtr_r : std_logic ; -- stepper motor on/off
signal freq : std_logic_vector(1 downto 0); -- motor (gcr_bit) frequency
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; -- activity LED
signal track_num_dbl : std_logic_vector(6 downto 0);
signal new_track_num_dbl : std_logic_vector(6 downto 0);
signal sd_busy : std_logic;
type byte_array is array(0 to 8191) of std_logic_vector(7 downto 0);
signal track_buffer : byte_array;
signal save_track : std_logic;
signal track_modified : std_logic;
signal sector_offset : std_logic;
signal save_track_stage : std_logic_vector(3 downto 0);
signal dbg_sector : std_logic_vector(4 downto 0);
signal dbg_adr_fetch : std_logic_vector(15 downto 0);
component mist_sd_card 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;
ram_addr : out std_logic_vector(12 downto 0);
ram_di : out std_logic_vector(7 downto 0);
ram_do : in std_logic_vector(7 downto 0);
ram_we : out std_logic;
sector_offset : out std_logic; -- 0 : sector 0 is at ram adr 0, 1 : sector 0 is at ram adr 256
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)
busy : out std_logic;
clk : in std_logic; -- System clock
reset : in std_logic
);
end component mist_sd_card;
begin
c1541 : entity work.c1541_logic
generic map
(
DEVICE_SELECT => "00"
)
port map
(
clk_32M => clk32,
reset => reset,
-- serial bus
sb_data_oe => iec_data_o,
sb_clk_oe => iec_clk_o,
sb_atn_oe => iec_atn_o,
sb_data_in => not iec_data_i,
sb_clk_in => not iec_clk_i,
sb_atn_in => not iec_atn_i,
-- drive-side interface
ds => "00", -- device select
di => c1541_logic_din, -- data read
do => c1541_logic_dout, -- data to write
mode => mode, -- read/write
stp => stp, -- stepper motor control
mtr => mtr, -- motor on/off
freq => freq, -- motor frequency
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
wps_n => '1', -- write-protect sense (0 = protected)
tr00_sense_n => '1', -- track 0 sense (unused?)
act => act, -- activity LED
dbg_adr_fetch => dbg_adr_fetch,
dbg_cpu_irq => open
);
floppy : entity work.gcr_floppy
port map
(
clk32 => clk32,
c1541_logic_din => c1541_logic_din, -- data read
c1541_logic_dout => c1541_logic_dout, -- data to write
mode => mode, -- read/write
-- stp => stp, -- stepper motor control
mtr => mtr, -- stepper motor on/off
-- freq => freq, -- motor (gcr_bit) frequency
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
track_num => new_track_num_dbl(6 downto 1),
ram_addr => floppy_ram_addr,
ram_do => ram_do,
ram_di => floppy_ram_di,
ram_we => floppy_ram_we,
ram_ready => not sd_busy,
dbg_sector => dbg_sector
);
-- mist_sd_card replaces work.spi_controller
sd: mist_sd_card
port map
(
clk => clk32,
reset => reset,
ram_addr => spi_ram_addr, -- out unsigned(13 downto 0);
ram_di => spi_ram_di, -- out unsigned(7 downto 0);
ram_do => ram_do, -- in unsigned(7 downto 0);
ram_we => spi_ram_we,
track => new_track_num_dbl(6 downto 1),
-- disk_num => disk_num,
busy => sd_busy,
save_track => save_track,
sector_offset => sector_offset,
change => disk_change,
sd_buff_addr => sd_buff_addr,
sd_buff_dout => sd_buff_dout,
sd_buff_din => sd_buff_din,
sd_buff_wr => sd_buff_wr,
sd_lba => sd_lba,
sd_rd => sd_rd,
sd_wr => sd_wr,
sd_ack => sd_ack
);
--sd_spi : entity work.spi_controller
--port map
--(
-- cs_n => sd_cs_n, --: out std_logic; -- MMC chip select
-- mosi => sd_mosi, --: out std_logic; -- Data to card (master out slave in)
-- miso => sd_miso, --: in std_logic; -- Data from card (master in slave out)
-- sclk => sd_sclk, --: out std_logic; -- Card clock
-- bus_available => bus_available,
--
-- ram_addr => spi_ram_addr, -- out unsigned(13 downto 0);
-- ram_di => spi_ram_di, -- out unsigned(7 downto 0);
-- ram_do => ram_do, -- in unsigned(7 downto 0);
-- ram_we => spi_ram_we,
--
-- track_num => new_track_num_dbl(6 downto 1),
-- disk_num => disk_num,
-- busy => sd_busy,
-- save_track => save_track,
-- sector_offset => sector_offset,
--
-- clk => clk_spi_ctrlr,
-- reset => reset,
--
-- dbg_state => dbg_sd_state
--);
process (clk32)
begin
if rising_edge(clk32) then
stp_r <= stp;
act_r <= act;
mode_r <= mode;
if reset = '1' then
track_num_dbl <= "0100100";--"0000010";
track_modified <= '0';
save_track_stage <= X"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';
if track_modified = '1' then
if save_track_stage = X"0" then
save_track_stage <= X"1";
end if;
else
new_track_num_dbl <= track_num_dbl + '1';
end if;
end if;
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';
if track_modified = '1' then
if save_track_stage = X"0" then
save_track_stage <= X"1";
end if;
else
new_track_num_dbl <= track_num_dbl - '1';
end if;
end if;
end if;
if mode_r = '0' and mode = '1' then -- leaving write mode
track_modified <= '1';
end if;
end if;
if act = '0' and act_r = '1' then -- stopping activity
if track_modified = '1' and save_track_stage = X"0" then
save_track_stage <= X"1";
end if;
end if;
-- save track state machine
case save_track_stage is
when X"0" =>
new_track_num_dbl <= track_num_dbl;
when X"1" =>
save_track <= '1';
if sd_busy = '1' then
save_track_stage <= X"2";
end if;
when X"2" =>
save_track_stage <= X"3";
when X"3" =>
save_track_stage <= X"4";
when X"4" =>
save_track <= '0'; -- must released save_track for spi_controler
if sd_busy = '0' then
save_track_stage <= X"5";
end if;
when X"5" =>
track_modified <= '0';
save_track_stage <= X"0";
when others =>
save_track_stage <= X"0";
end case;
end if; -- reset
end if; -- rising edge clock
end process;
process(clk32)
begin
if falling_edge(clk32) then
if ram_we = '1' then
track_buffer(to_integer(unsigned(ram_addr))) <= ram_di;
end if;
ram_do <= track_buffer(to_integer(unsigned(ram_addr)));
end if;
end process;
ram_addr <= spi_ram_addr when sd_busy = '1' else floppy_ram_addr + ("000"&sector_offset&X"00");
ram_we <= spi_ram_we when sd_busy = '1' else floppy_ram_we;
ram_di <= spi_ram_di when sd_busy = '1' else floppy_ram_di;
process (clk32)
begin
if rising_edge(clk32) then
if dbg_adr_fetch = X"F4D7" then
dbg_read_sector <= dbg_sector;
end if;
end if;
end process;
dbg_sd_busy <= sd_busy;
dbg_track_num_dbl <= new_track_num_dbl;
dbg_mtr <= mtr;
dbg_act <= act;
led <= act;
end struct;

View File

@@ -0,0 +1,318 @@
---------------------------------------------------------------------------------
-- 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;
c1541_logic_din : out std_logic_vector(7 downto 0); -- data from ram to 1541 logic
c1541_logic_dout : in std_logic_vector(7 downto 0); -- data from 1541 logic to ram
mode : in std_logic; -- read/write
-- stp : in std_logic_vector(1 downto 0); -- stepper motor control
mtr : in std_logic; -- stepper motor on/off
-- freq : in std_logic_vector(1 downto 0); -- motor (gcr_bit) frequency
sync_n : out std_logic; -- reading SYNC bytes
byte_n : out std_logic; -- byte ready
track_num : in std_logic_vector(5 downto 0);
ram_addr : out std_logic_vector(12 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;
dbg_sector : out std_logic_vector(4 downto 0)
);
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 : 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';
dbg_sector <= sector;
with byte_cnt select
data_header <=
X"08" when "000000000",
"00"&track_num xor "000"&sector when "000000001",
"000"&sector when "000000010",
"00"&track_num 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_num < std_logic_vector(to_unsigned(18,6)) else
"10010" when track_num < std_logic_vector(to_unsigned(25,6)) else
"10001" when track_num < 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) and 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');
c1541_logic_din <= (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';
ram_addr <= sector & 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 <= c1541_logic_dout;
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 = sector_max then
sector <= (others=>'0');
else
sector <= sector + '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
c1541_logic_din <= 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;
else
ram_we <= '0';
end if;
end if;
end if;
end process;
end struct;

View File

@@ -0,0 +1,128 @@
//
// sd_card.v
//
// 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 mist_sd_card
(
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,
output [12:0] ram_addr,
output [7:0] ram_di,
input [7:0] ram_do,
output ram_we,
output reg sector_offset, // 0 : sector 0 is at ram adr 0,
// 1 : sector 0 is at ram adr 256
output reg busy
);
assign sd_lba = lba;
assign ram_addr = { rel_lba, sd_buff_addr};
assign ram_di = sd_buff_dout;
assign sd_buff_din = ram_do;
assign ram_we = sd_buff_wr;
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 [3:0] rel_lba;
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(~&rel_lba) begin
lba <= lba + 1'd1;
rel_lba <= rel_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;
rel_lba <= 0;
sector_offset <= start_sectors[track][0] ;
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;
lba <= start_sectors[cur_track][9:1];
rel_lba <= 0;
sd_wr <= 1;
busy <= 1;
end
else
if((cur_track != track) || (old_change && ~change)) begin
saving <= 0;
cur_track <= track;
rel_lba <= 0;
sector_offset <= start_sectors[track][0] ;
lba <= start_sectors[track][9:1];
sd_rd <= 1;
busy <= 1;
end
end
end
endmodule

View File

@@ -9,39 +9,61 @@
-- Stephen A. Edwards (sedwards@cs.columbia.edu)
--
-------------------------------------------------------------------------------
-- Principle : (after card init)
-- * read track_size data (26*256 bytes) from sd card to ram buffer when
-- disk_num or track_num change
-- * write track_size data back from ram buffer to sd card when save_track
-- is pulsed to '1'
--
-- Data read from sd_card always start on 512 bytes boundaries.
-- When actual D64 track starts on 512 bytes boundary sector_offset is set
-- to 0.
-- When actual D64 track starts on 256 bytes boundary sector_offset is set
-- to 1.
-- External ram buffer 'user' should mind sector_offset to retrieve correct
-- data offset.
--
-- One should be advised that extra bytes may be read and write out of disk
-- boundary when using last track. With a single sd card user this should
-- lead to no problem since written data always comes from the exact same
-- read place (extra written data will replaced same value on disk).
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity spi_controller is
generic (
BLOCK_SIZE : natural := 512;
BLOCK_BITS : natural := 9;
-- BLOCK_SIZE : natural := 256;
-- BLOCK_BITS : natural := 8;
TRACK_SIZE : natural := 16#1A00#
BLOCK_SIZE : natural := 512; -- necessary for block write
BLOCK_BITS : natural := 9;
TRACK_SIZE : natural := 16#1A00#
);
port (
-- Card Interface ---------------------------------------------------------
CS_N : out std_logic; -- MMC chip select
MOSI : out std_logic; -- Data to card (master out slave in)
MISO : in std_logic; -- Data from card (master in slave out)
SCLK : out std_logic; -- Card clock
cs_n : out std_logic; -- sd card chip select
mosi : out std_logic; -- data to sd card (master out slave in)
miso : in std_logic; -- data from sd card (master in slave out)
sclk : out std_logic; -- sd card clock
bus_available : in std_logic; -- Spi bus available
-- Track buffer Interface -------------------------------------------------
ram_write_addr : out unsigned(12 downto 0);
ram_di : out unsigned(7 downto 0);
ram_addr : out std_logic_vector(12 downto 0);
ram_di : out std_logic_vector(7 downto 0);
ram_do : in std_logic_vector(7 downto 0);
ram_we : out std_logic;
change : in std_logic; -- Force reload as disk may have changed
track : in unsigned(5 downto 0); -- Track number (0-34)
image : in unsigned(9 downto 0); -- Which disk image to read
busy : out std_logic;
-- System Interface -------------------------------------------------------
CLK_14M : in std_logic; -- System clock
reset : in std_logic;
dbg_state : out std_logic_vector(7 downto 0) -- DTX
track_num : in std_logic_vector(5 downto 0); -- Track number (0/1-40)
disk_num : in std_logic_vector(9 downto 0); -- Which disk image to read
busy : buffer std_logic;
save_track : in std_logic; -- pulse to 1 to write ram buffer back to sd card
sector_offset : out std_logic; -- 0 : sector 0 is at ram adr 0, 1 : sector 0 is at ram adr 256
-- System Interface -------------------------------------------------------
clk : in std_logic; -- System clock
reset : in std_logic;
-- Debug ------------------------------------------------------------------
dbg_state : out std_logic_vector(7 downto 0)
);
end spi_controller;
@@ -69,6 +91,12 @@ architecture rtl of spi_controller is
READ_BLOCK_WAIT,
READ_BLOCK_DATA,
READ_BLOCK_CRC,
-- Track write FSM
WRITE_TRACK,
WRITE_BLOCK_INIT,
WRITE_BLOCK_DATA,
WRITE_BYTE,
WRITE_BLOCK_WAIT,
-- SD command embedded FSM
WAIT_NRC,
SEND_CMD,
@@ -80,48 +108,34 @@ architecture rtl of spi_controller is
-----------------------------------------------------------------------------
signal slow_clk : boolean := true;
signal spi_clk : std_logic;
signal spi_clk : std_logic;
signal sclk_sig : std_logic;
signal current_track : unsigned(5 downto 0);
signal current_image : unsigned(9 downto 0);
-- signal write_addr : unsigned(13 downto 0);
signal write_addr : unsigned(12 downto 0);
signal current_track_num : std_logic_vector(5 downto 0); -- track number currently in buffer
signal current_disk_num : std_logic_vector(9 downto 0); -- disk number currently in buffer
signal ram_addr_in : std_logic_vector(12 downto 0) := (others => '0');
signal command : std_logic_vector(5 downto 0);
signal argument : std_logic_vector(31 downto 0);
signal crc7 : std_logic_vector(6 downto 0);
signal command : std_logic_vector(5 downto 0);
signal argument : std_logic_vector(31 downto 0);
signal crc7 : std_logic_vector(6 downto 0);
signal command_out : std_logic_vector(55 downto 0);
signal recv_bytes : unsigned(39 downto 0);
signal recv_bytes : std_logic_vector(39 downto 0);
type versions is (MMC, SD1x, SD2x);
signal version : versions;
signal version : versions;
signal high_capacity : boolean;
-- C64 - 1541 start_sector in D64 format per track number [0..40]
type start_sector_array_type is array(0 to 40) of integer range 0 to 1023;
constant start_sector_array : start_sector_array_type :=
( 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);
signal start_sector : std_logic_vector(9 downto 0);
signal reload : std_logic;
type start_sector_array_type is array(0 to 40) of integer range 0 to 1023;
signal start_sector_array : start_sector_array_type :=
( 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);
signal start_sector_addr : std_logic_vector(9 downto 0); -- addresse of sector within full disk
signal cmd_data_mode : std_logic := '1'; -- 1:command to sd card, 0:data to sd card
signal data_to_write : std_logic_vector(7 downto 0) := X"00";
begin
-- set reload flag whenever "change" rises and clear it once the
-- state machine starts reloading the track
process(change, state)
begin
if(state = READ_TRACK) then
reload <= '0';
else
if rising_edge(change) then
reload <= '1';
end if;
end if;
end process;
--ram_write_addr <= write_addr;
-----------------------------------------------------------------------------
-- Process var_clkgen
--
@@ -130,26 +144,26 @@ begin
-- If slow_clk is false, spi_clk == CLK_14M, thus SCLK = 7M
-- If slow_clk is true, spi_clk = CLK_14M / 32 and SCLK = 223.214kHz, which
-- is between 100kHz and 400kHz, as required for MMC compatibility.
--
--
var_clkgen : process (CLK_14M, slow_clk)
var_clkgen : process (clk, slow_clk)
variable var_clk : unsigned(4 downto 0) := (others => '0');
begin
if slow_clk then
spi_clk <= var_clk(4);
if rising_edge(CLK_14M) then
if rising_edge(clk) then
var_clk := var_clk + 1;
end if;
else
spi_clk <= CLK_14M;
spi_clk <= clk;
end if;
end process;
SCLK <= sclk_sig;
sclk <= sclk_sig;
--
-----------------------------------------------------------------------------
start_sector_addr <= std_logic_vector(to_unsigned(start_sector_array(to_integer(unsigned(track_num))),10));
sector_offset <= start_sector_addr(0);
-----------------------------------------------------------------------------
-- Process sd_fsm
--
@@ -163,36 +177,38 @@ begin
constant CMD8 : cmd_t := std_logic_vector(to_unsigned(8, 6));
constant CMD16 : cmd_t := std_logic_vector(to_unsigned(16, 6));
constant CMD17 : cmd_t := std_logic_vector(to_unsigned(17, 6));
constant CMD24 : cmd_t := std_logic_vector(to_unsigned(24, 6));
constant CMD55 : cmd_t := std_logic_vector(to_unsigned(55, 6));
constant CMD58 : cmd_t := std_logic_vector(to_unsigned(58, 6));
constant ACMD41 : cmd_t := std_logic_vector(to_unsigned(41, 6));
variable counter : unsigned(7 downto 0);
variable byte_counter : unsigned(BLOCK_BITS - 1 downto 0);
variable lba : unsigned(31 downto 0);
variable byte_counter : unsigned(BLOCK_BITS downto 0);
variable lba : std_logic_vector(31 downto 0);
begin
if rising_edge(spi_clk) then
ram_we <= '0';
if reset = '1' then
state <= POWER_UP;
state <= POWER_UP;
-- Deliberately out of range
current_track <= (others => '1');
current_image <= (others => '1');
sclk_sig <= '0';
slow_clk <= true;
CS_N <= '1';
command <= (others => '0');
argument <= (others => '0');
crc7 <= (others => '0');
command_out <= (others => '1');
counter := TO_UNSIGNED(0, 8);
byte_counter := TO_UNSIGNED(0, BLOCK_BITS);
write_addr <= (others => '0');
high_capacity <= false;
version <= MMC;
lba := (others => '0');
busy <= '1';
dbg_state <= x"00";
current_track_num <= (others => '1');
current_disk_num <= (others => '1');
sclk_sig <= '0';
slow_clk <= true;
cs_n <= '1';
cmd_data_mode <= '1';
command <= (others => '0');
argument <= (others => '0');
crc7 <= (others => '0');
command_out <= (others => '1');
counter := TO_UNSIGNED(0, 8);
byte_counter := TO_UNSIGNED(0, BLOCK_BITS+1);
ram_addr_in <= (others => '0');
high_capacity <= false;
version <= MMC;
lba := (others => '0');
busy <= '1';
dbg_state <= x"00";
else
case state is
@@ -207,12 +223,15 @@ begin
-- greater) to wake up the card
when RAMP_UP =>
if counter = 0 then
CS_N <= '0';
cs_n <= '0';
command <= CMD0;
argument <= (others => '0');
crc7 <= "1001010";
return_state <= CHECK_CMD0;
state <= WAIT_NRC;
return_state <= CHECK_CMD0;
if bus_available = '1' then
state <= WAIT_NRC;
end if;
else
counter := counter - 1;
sclk_sig <= not sclk_sig;
@@ -347,78 +366,52 @@ begin
when ERROR =>
sclk_sig <= '0';
slow_clk <= true;
CS_N <= '1';
cs_n <= '1';
---------------------------------------------------------------------
-- Embedded "read track" FSM
---------------------------------------------------------------------
-- Idle state where we sit waiting for user image/track requests ----
when IDLE =>
dbg_state <= x"01";
if reload='1' or track /= current_track or image /= current_image then
----------------------------------------------------------
-- Compute the LBA (Logical Block Address) from the given
-- image/track numbers.
-- Each Apple ][ floppy image contains 35 tracks, each consisting of
-- 16 x 256-byte sectors.
-- However, because of inter-sector gaps and address fields in
-- raw mode, the actual length is set to 0x1A00, so each image is
-- actually $1A00 bytes * 0x23 tracks = 0x38E00 bytes.
-- So: lba = image * 0x38E00 + track * 0x1A00
-- In order to avoid multiplications by constants, we replace
-- them by direct add/sub of shifted image/track values:
-- 0x38E00 = 0011 1000 1110 0000 0000
-- = 0x40000 - 0x8000 + 0x1000 - 0x200
-- 0x01A00 = 0000 0001 1010 0000 0000
-- = 0x1000 + 0x800 + 0x200
------------------------------------------------------
--lba := ("0000" & image & "000000000000000000") -
-- ( image & "000000000000000") +
-- ( image & "000000000000") -
-- ( image & "000000000") +
-- ( track & "000000000") +
-- ( track & "00000000000") +
-- ( track & "000000000000");
------------------------------------------------------
-- For C64 1541 format D64 image must start every 256Ko --
lba := (X"0" & image &
to_unsigned(start_sector_array(to_integer(unsigned(track))),10) &
X"00");
-- check if track starts at 512 byte boundary ...
if to_unsigned(start_sector_array(to_integer(unsigned(track))),10)(0)='1' then
-- ... no it doesn't. We thus start writing before the begin of the
-- buffer so the first 256 bytes are effectively skipped
write_addr <= "1111100000000";
else
-- ... yes it does. We can just load the track to memory
write_addr <= (others => '0');
end if;
if high_capacity then
-- TODO: This probably doesn't work in the same process where lba is set
-- For SDHC, blocks are addressed by blocks, not bytes
lba := lba srl BLOCK_BITS;
end if;
-- write_addr <= (others => '0');
CS_N <= '0';
state <= READ_TRACK;
current_track <= track;
current_image <= image;
busy <= '1';
else
CS_N <= '1';
sclk_sig <= '1';
busy <= '0';
end if;
-- Idle state where we sit waiting for user image/track change or
-- save request
when IDLE =>
dbg_state <= x"01";
-- For C64 1541 format D64 image (disk_num) must start every 256Ko --
lba := (X"0" & disk_num & start_sector_addr(9 downto 1) & '0' & X"00");
if high_capacity then
-- For SDHC, blocks are addressed by blocks, not bytes
lba := std_logic_vector(to_unsigned(0,BLOCK_BITS)) & lba(31 downto BLOCK_BITS);
end if;
ram_addr_in <= (others => '0');
sclk_sig <= '1';
cs_n <= '0';
busy <= '0';
if save_track = '1' then
if bus_available = '1' then
busy <= '1';
state <= WRITE_TRACK;
end if;
else
if track_num /= current_track_num or disk_num /= current_disk_num then
if bus_available = '1' then -- and busy = '1' then
busy <= '1';
state <= READ_TRACK;
end if;
else
cs_n <= '1';
end if;
end if;
-- Read in a whole track into buffer memory -------------------------
when READ_TRACK =>
dbg_state <= x"02";
if write_addr = TRACK_SIZE or write_addr = (TRACK_SIZE-256) then
state <= IDLE;
dbg_state <= x"02";
if ram_addr_in = std_logic_vector(to_unsigned(TRACK_SIZE,13)) then
state <= IDLE;
current_track_num <= track_num;
current_disk_num <= disk_num;
else
command <= CMD17;
argument <= std_logic_vector(lba);
@@ -428,10 +421,10 @@ begin
-- Wait for a 0 bit to signal the start of the block ----------------
when READ_BLOCK_WAIT =>
dbg_state <= x"03";
if sclk_sig = '1' and MISO = '0' then
dbg_state <= x"03";
if sclk_sig = '1' and miso = '0' then
state <= READ_BLOCK_DATA;
byte_counter := TO_UNSIGNED(BLOCK_SIZE - 1, BLOCK_BITS);
byte_counter := TO_UNSIGNED(BLOCK_SIZE - 1, BLOCK_BITS+1);
counter := TO_UNSIGNED(7, 8);
return_state <= READ_BLOCK_DATA;
state <= RECEIVE_BYTE;
@@ -440,10 +433,10 @@ begin
-- Read a block of data ---------------------------------------------
when READ_BLOCK_DATA =>
dbg_state <= x"04";
dbg_state <= x"04";
ram_we <= '1';
write_addr <= write_addr + 1;
ram_write_addr <= write_addr;
ram_addr_in <= ram_addr_in + '1';
ram_addr <= ram_addr_in;
if byte_counter = 0 then
counter := TO_UNSIGNED(7, 8);
return_state <= READ_BLOCK_CRC;
@@ -457,7 +450,7 @@ begin
-- Read the block CRC -----------------------------------------------
when READ_BLOCK_CRC =>
dbg_state <= x"05";
dbg_state <= x"05";
counter := TO_UNSIGNED(7, 8);
return_state <= READ_TRACK;
if high_capacity then
@@ -466,13 +459,93 @@ begin
lba := lba + BLOCK_SIZE;
end if;
state <= RECEIVE_BYTE;
---------------------------------------------------------------------
-- write track FSM
---------------------------------------------------------------------
-- write out a whole track from buffer memory -------------------------
when WRITE_TRACK =>
dbg_state <= x"11";
cmd_data_mode <= '1';
if ram_addr_in = std_logic_vector(to_unsigned(TRACK_SIZE,13)) then
state <= IDLE;
else
command <= CMD24;
argument <= std_logic_vector(lba);
return_state <= WRITE_BLOCK_INIT;
if save_track = '0' then -- wait cmd released
state <= WAIT_NRC;
dbg_state <= x"12";
end if;
end if;
-- Wait for a 0 bit to signal the start of the block ----------------
when WRITE_BLOCK_INIT =>
dbg_state <= x"13";
cmd_data_mode <= '0';
state <= WRITE_BLOCK_DATA;
byte_counter := TO_UNSIGNED(BLOCK_SIZE +3 , BLOCK_BITS+1);
counter := TO_UNSIGNED(7, 8);
-- write a block of data ---------------------------------------------
when WRITE_BLOCK_DATA =>
dbg_state <= x"14";
if byte_counter = 0 then
return_state <= WRITE_BLOCK_WAIT;
state <= RECEIVE_BYTE_WAIT;
else
if byte_counter = TO_UNSIGNED(1, BLOCK_BITS+1) or
byte_counter = TO_UNSIGNED(2, BLOCK_BITS+1) then
data_to_write <= X"FF";
elsif byte_counter = TO_UNSIGNED(BLOCK_SIZE +3 , BLOCK_BITS+1) then
data_to_write <= X"FE";
ram_addr <= ram_addr_in;
else
data_to_write <= ram_do;
ram_addr_in <= ram_addr_in + '1';
ram_addr <= ram_addr_in + '1';
end if;
counter := TO_UNSIGNED(7, 8);
state <= WRITE_BYTE;
byte_counter := byte_counter - 1;
end if;
-- write one byte --- -----------------------------------------------
when WRITE_BYTE =>
dbg_state <= x"15";
if sclk_sig = '1' then
if counter = 0 then
state <= WRITE_BLOCK_DATA;
else
counter := counter - 1;
data_to_write <= data_to_write(6 downto 0) & "1";
end if;
end if;
sclk_sig <= not sclk_sig;
-- wait end of write -----------------------------------------------
when WRITE_BLOCK_WAIT =>
dbg_state <= x"16";
if sclk_sig = '1' then
if miso = '1' then
dbg_state <= x"17";
state <= WRITE_TRACK;
if high_capacity then
lba := lba + 1;
else
lba := lba + BLOCK_SIZE;
end if;
end if;
end if;
sclk_sig <= not sclk_sig;
---------------------------------------------------------------------
-- Embedded "command" FSM
---------------------------------------------------------------------
-- Wait for card response in front of host command ------------------
when WAIT_NRC =>
dbg_state <= x"06";
dbg_state <= x"06";
counter := TO_UNSIGNED(63, 8);
command_out <= "11111111" & "01" & command & argument & crc7 & "1";
sclk_sig <= not sclk_sig;
@@ -480,7 +553,7 @@ begin
-- Send a command to the card ---------------------------------------
when SEND_CMD =>
dbg_state <= x"07";
dbg_state <= x"07";
if sclk_sig = '1' then
if counter = 0 then
state <= RECEIVE_BYTE_WAIT;
@@ -493,9 +566,9 @@ begin
-- Wait for a "0", indicating the first bit of a response -----------
when RECEIVE_BYTE_WAIT =>
dbg_state <= x"08";
dbg_state <= x"08";
if sclk_sig = '1' then
if MISO = '0' then
if miso = '0' then
recv_bytes <= (others => '0');
if command = CMD8 or command = CMD58 then
-- This is an R7 response, but we already have read bit 39
@@ -512,24 +585,26 @@ begin
-- Receive a byte ---------------------------------------------------
when RECEIVE_BYTE =>
dbg_state <= x"09";
dbg_state <= x"09";
if sclk_sig = '1' then
recv_bytes <= recv_bytes(38 downto 0) & MISO;
recv_bytes <= recv_bytes(38 downto 0) & miso;
if counter = 0 then
state <= return_state;
ram_di <= recv_bytes(6 downto 0) & MISO;
ram_di <= recv_bytes(6 downto 0) & miso;
else
counter := counter - 1;
end if;
end if;
sclk_sig <= not sclk_sig;
when others => null;
when others =>
dbg_state <= x"1F";
end case;
end if;
end if;
end process sd_fsm;
MOSI <= command_out(55);
mosi <= command_out(55) when cmd_data_mode = '1' else data_to_write(7);
end rtl;

84
cores/c16/c1541/spram.vhd Normal file
View File

@@ -0,0 +1,84 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY spram IS
GENERIC
(
init_file : string := "";
numwords_a : natural := 0; -- not used
widthad_a : natural;
width_a : natural := 8;
outdata_reg_a : string := "UNREGISTERED"
);
PORT
(
address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
clock : IN STD_LOGIC ;
data : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
wren : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
);
END spram;
ARCHITECTURE SYN OF spram IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
power_up_uninitialized : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
wren_a : IN STD_LOGIC ;
clock0 : IN STD_LOGIC ;
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(width_a-1 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => init_file,
intended_device_family => "Cyclone II",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 2**widthad_a,
operation_mode => "SINGLE_PORT",
outdata_aclr_a => "NONE",
outdata_reg_a => outdata_reg_a,
power_up_uninitialized => "FALSE",
widthad_a => widthad_a,
width_a => width_a,
width_byteena_a => 1
)
PORT MAP (
wren_a => wren,
clock0 => clock,
address_a => address,
data_a => data,
q_a => sub_wire0
);
END SYN;

77
cores/c16/c1541/sprom.vhd Normal file
View File

@@ -0,0 +1,77 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY sprom IS
GENERIC
(
init_file : string := "";
numwords_a : natural := 0; -- not used any more
widthad_a : natural;
width_a : natural := 8;
outdata_reg_a : string := "UNREGISTERED"
);
PORT
(
address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
clock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
);
END sprom;
ARCHITECTURE SYN OF sprom IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
clock0 : IN STD_LOGIC ;
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(width_a-1 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => init_file,
intended_device_family => "Cyclone II",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 2**widthad_a,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => outdata_reg_a,
widthad_a => widthad_a,
width_a => width_a,
width_byteena_a => 1
)
PORT MAP (
clock0 => clock,
address_a => address,
q_a => sub_wire0
);
END SYN;

View File

@@ -1,366 +0,0 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
--use work.platform_pkg.all;
--use work.project_pkg.all;
--
-- Model 1541B
--
entity c1541_logic is generic(DEVICE_SELECT : std_logic_vector(1 downto 0));
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_oe : out std_logic;
sb_atn_in : 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 write data
do : out std_logic_vector(7 downto 0); -- disk read 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, reset
signal reset_n : std_logic;
signal clk_4M_en : std_logic;
signal p2_h : std_logic;
signal clk_1M_pulse : std_logic;
-- cpu signals
signal cpu_a : unsigned(15 downto 0);
signal cpu_di : unsigned(7 downto 0);
signal cpu_do : unsigned(7 downto 0);
signal cpu_a_l : std_logic_vector(23 downto 0);
signal cpu_do_l : std_logic_vector(7 downto 0);
signal cpu_rw : std_logic;
signal cpu_rw_n : 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_cs1 : std_logic;
signal uc1_cs2_n : std_logic;
signal uc1_irq_n : std_logic;
signal uc1_ca1_i : std_logic;
signal uc1_pa_i : std_logic_vector(7 downto 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_cs1 : std_logic;
signal uc3_cs2_n : 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;
begin
reset_n <= not reset;
process (clk_32M, reset)
variable count : std_logic_vector(8 downto 0) := (others => '0');
alias hcnt : std_logic_vector(1 downto 0) is count(4 downto 3);
begin
if rising_edge(clk_32M) then
-- generate 1MHz pulse
clk_1M_pulse <= '0';
--if count(4 downto 0) = "00111" then
if count(4 downto 0) = "01000" then
clk_1M_pulse <= '1';
end if;
-- if count = "000100000" then -- DAR divide by 33 (otherwise real c64 miss EOI acknowledge)
if count = "000011111" then -- TH: divide by 32
count := (others => '0'); -- DAR
else -- DAR
count := std_logic_vector(unsigned(count) + 1);
end if; -- DAR
end if;
p2_h <= not hcnt(1);
-- for original m6522 design that requires a real clock
-- clk_4M_en <= not count(2);
-- for version 002 with clock enable
if count(2 downto 0) = "111" then
clk_4M_en <= '1';
else
clk_4M_en <= '0';
end if;
end process;
-- decode logic
-- RAM $0000-$07FF (2KB)
ram_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "00000-----------") else '0';
-- UC1 (VIA6522) $1800-$180F
uc1_cs2_n <= '0' when STD_MATCH(cpu_a(15 downto 0), "000110000000----") else '1';
-- UC3 (VIA6522) $1C00-$1C0F
uc3_cs2_n <= '0' when STD_MATCH(cpu_a(15 downto 0), "000111000000----") else '1';
-- ROM $C000-$FFFF (16KB)
rom_cs <= '1' when STD_MATCH(cpu_a(15 downto 0), "11--------------") else '0';
-- qualified write signals
ram_wr <= '1' when ram_cs = '1' and cpu_rw = '1' else '0';
--
-- hook up UC1 ports
--
uc1_cs1 <= cpu_a(11);
--uc1_cs2_n: see decode logic above
-- CA1
--uc1_ca1_i <= not sb_atn_in; -- DAR comment : synched with clk_4M_en see below
-- PA
uc1_pa_i(0) <= tr00_sense_n;
uc1_pa_i(7 downto 1) <= (others => '0'); -- NC
-- PB
uc1_pb_i(0) <= '1' when sb_data_in = '0' else
'1' when (uc1_pb_o(1) = '1' and uc1_pb_oe_n(1) = '0') else -- DAR comment : external OR wired
'1' when atn = '1' else -- DAR comment : external OR wired
'0';
sb_data_oe <= '1' when (uc1_pb_o(1) = '1' and uc1_pb_oe_n(1) = '0') else
'1' when atn = '1' else
'0';
uc1_pb_i(2) <= '1' when sb_clk_in = '0' else
'1' when (uc1_pb_o(3) = '1' and uc1_pb_oe_n(3) = '0') else -- DAR comment : external OR wired
'0';
sb_clk_oe <= '1' when (uc1_pb_o(3) = '1' and uc1_pb_oe_n(3) = '0') else '0';
atna <= uc1_pb_o(4); -- when uc1_pc_oe = '1'
uc1_pb_i(6 downto 5) <= DEVICE_SELECT xor ds; -- allows override
uc1_pb_i(7) <= not sb_atn_in;
--
-- hook up UC3 ports
--
uc3_cs1 <= cpu_a(11);
--uc3_cs2_n: see decode logic above
-- CA1
uc3_ca1_i <= cpu_so_n; -- byte ready gated with soe
-- CA2
soe <= uc3_ca2_o or uc3_ca2_oe_n;
-- PA
uc3_pa_i <= di;
do <= uc3_pa_o or uc3_pa_oe_n;
-- CB2
mode <= uc3_cb2_o or uc3_cb2_oe_n;
-- PB
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 <= unsigned(rom_do) when rom_cs = '1' else
unsigned(ram_do) when ram_cs = '1' else
unsigned(uc1_do) when (uc1_cs1 = '1' and uc1_cs2_n = '0') else
unsigned(uc3_do) when (uc3_cs1 = '1' and uc3_cs2_n = '0') 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);
-- external connections
-- ATN never driven by the 1541
sb_atn_oe <= '0';
-- DAR
process (clk_32M)
begin
if rising_edge(clk_32M) then
if clk_4M_en = '1' then
uc1_ca1_i <= not sb_atn_in; -- DAR sample external atn to ensure not missing edge within VIA
end if;
end if;
end process;
cpu: entity work.cpu65xx
generic map (
pipelineOpcode => false,
pipelineAluMux => false,
pipelineAluOut => false
)
port map (
clk => clk_32M,
enable => clk_1M_pulse,
reset => reset,
nmi_n => '1',
irq_n => cpu_irq_n,
so_n => cpu_so_n,
di => cpu_di,
do => cpu_do,
addr => cpu_a,
we => cpu_rw
);
rom_inst: entity work.rom_C1541
port map (
clock => clk_32M,
wren => c1541rom_wr,
data => c1541rom_data,
wraddress => c1541rom_addr,
rdaddress => std_logic_vector(cpu_a(13 downto 0)),
q => rom_do
);
process (clk_32M)
begin
if rising_edge(clk_32M) then
ram_do <= ram(to_integer(cpu_a(13 downto 0)));
if ram_wr = '1' then
ram(to_integer(cpu_a(13 downto 0))) <= std_logic_vector(cpu_do);
end if;
end if;
end process;
uc1_via6522_inst : entity work.M6522
port map
(
I_RS => std_logic_vector(cpu_a(3 downto 0)),
I_DATA => std_logic_vector(cpu_do),
O_DATA => uc1_do,
O_DATA_OE_L => open,
I_RW_L => not cpu_rw,
I_CS1 => uc1_cs1,
I_CS2_L => uc1_cs2_n,
O_IRQ_L => uc1_irq_n,
-- port a
I_CA1 => uc1_ca1_i,
I_CA2 => '0',
O_CA2 => open,
O_CA2_OE_L => open,
I_PA => uc1_pa_i,
O_PA => open,
O_PA_OE_L => open,
-- port b
I_CB1 => '0',
O_CB1 => open,
O_CB1_OE_L => open,
I_CB2 => '0',
O_CB2 => open,
O_CB2_OE_L => open,
I_PB => uc1_pb_i,
O_PB => uc1_pb_o,
O_PB_OE_L => uc1_pb_oe_n,
RESET_L => reset_n,
CLK => clk_32M,
I_P2_H => p2_h, -- high for phase 2 clock ____----__
ENA_4 => clk_4M_en -- 4x system clock (4MHZ) _-_-_-_-_-
);
uc3_via6522_inst : entity work.M6522
port map
(
I_RS => std_logic_vector(cpu_a(3 downto 0)),
I_DATA => std_logic_vector(cpu_do),
O_DATA => uc3_do,
O_DATA_OE_L => open,
I_RW_L => not cpu_rw,
I_CS1 => cpu_a(11),
I_CS2_L => uc3_cs2_n,
O_IRQ_L => uc3_irq_n,
-- port a
I_CA1 => uc3_ca1_i,
I_CA2 => '0',
O_CA2 => uc3_ca2_o,
O_CA2_OE_L => uc3_ca2_oe_n,
I_PA => uc3_pa_i,
O_PA => uc3_pa_o,
O_PA_OE_L => uc3_pa_oe_n,
-- port b
I_CB1 => '0',
O_CB1 => open,
O_CB1_OE_L => open,
I_CB2 => '0',
O_CB2 => uc3_cb2_o,
O_CB2_OE_L => uc3_cb2_oe_n,
I_PB => uc3_pb_i,
O_PB => uc3_pb_o,
O_PB_OE_L => uc3_pb_oe_n,
RESET_L => reset_n,
CLK => clk_32M,
I_P2_H => p2_h, -- high for phase 2 clock ____----__
ENA_4 => clk_4M_en -- 4x system clock (4MHZ) _-_-_-_-_-
);
end SYN;

View File

@@ -1,217 +0,0 @@
---------------------------------------------------------------------------------
-- Commodore 1541 to SD card (read only) by Dar (darfpga@aol.fr) 02-April-2015
-- http://darfpga.blogspot.fr
--
-- c1541_sd reads D64 data from raw SD card, produces GCR data, feeds c1541_logic
-- Raw SD data : each D64 image must start on 256KB boundaries
-- disk_num allow to select D64 image
--
-- c1541_logic from : Mark McDougall
-- spi_controller from : Michel Stempin, Stephen A. Edwards
-- via6522 from : Arnim Laeuger, Mark McDougall, MikeJ
-- T65 from : Daniel Wallner, MikeJ, ehenciak
--
-- 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)
-- spi_controller modified for : sector start and size adapted + busy signal
-- via6522 modified for : no modification
--
--
-- Input clk 32MHz and 18MHz (18MHz could be replaced with 32/2 if needed)
--
---------------------------------------------------------------------------------
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;
clk18 : in std_logic;
reset : in std_logic;
disk_change : in std_logic;
disk_num : in std_logic_vector(9 downto 0);
iec_atn_i : in std_logic;
iec_data_i : in std_logic;
iec_clk_i : in std_logic;
iec_atn_o : out std_logic;
iec_data_o : out std_logic;
iec_clk_o : out std_logic;
sd_dat : in std_logic;
sd_dat3 : buffer std_logic;
sd_cmd : buffer std_logic;
sd_clk : buffer std_logic;
led : out std_logic_vector(7 downto 0);
c1541rom_addr : in std_logic_vector(13 downto 0);
c1541rom_data : in std_logic_vector(7 downto 0);
c1541rom_wr : in std_logic
);
end c1541_sd;
architecture struct of c1541_sd is
signal ram_write_addr : unsigned(12 downto 0);
signal ram_addr : unsigned(12 downto 0);
signal ram_di : unsigned( 7 downto 0);
signal ram_do : unsigned( 7 downto 0);
signal ram_we : std_logic;
signal do : std_logic_vector(7 downto 0); -- disk read 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 freq : std_logic_vector(1 downto 0); -- motor (gcr_bit) frequency
signal sync_n : std_logic; -- reading SYNC bytes
signal byte_n : std_logic; -- byte ready
signal act : std_logic; -- activity LED
signal track_dbl : std_logic_vector(6 downto 0);
signal sd_busy : std_logic;
signal track_read_adr : std_logic_vector(12 downto 0);
begin
c1541 : entity work.c1541_logic
generic map
(
DEVICE_SELECT => "00"
)
port map
(
clk_32M => clk32,
reset => reset,
-- serial bus
sb_data_oe => iec_data_o,
sb_clk_oe => iec_clk_o,
sb_atn_oe => iec_atn_o,
sb_data_in => not iec_data_i,
sb_clk_in => not iec_clk_i,
sb_atn_in => not iec_atn_i,
c1541rom_addr => c1541rom_addr,
c1541rom_data => c1541rom_data,
c1541rom_wr => c1541rom_wr,
-- drive-side interface
ds => "00", -- device select
di => do, -- disk write data
do => open, -- disk read data
mode => mode, -- read/write
stp => stp, -- stepper motor control
mtr => mtr, -- motor on/off
freq => freq, -- motor frequency
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
wps_n => '0', -- write-protect sense
tr00_sense_n => '1', -- track 0 sense (unused?)
act => act -- activity LED
);
floppy : entity work.gcr_floppy
port map
(
clk32 => clk32,
do => do, -- disk read data
mode => mode, -- read/write
stp => stp, -- stepper motor control
mtr => mtr, -- stepper motor on/off
freq => freq, -- motor (gcr_bit) frequency
sync_n => sync_n, -- reading SYNC bytes
byte_n => byte_n, -- byte ready
track => track_dbl(6 downto 1),
track_adr => track_read_adr,
track_data => std_logic_vector(ram_do),
track_ready => not sd_busy
);
process (clk32)
begin
if rising_edge(clk32) then
stp_r <= stp;
if reset = '1' then
track_dbl <= "0000010";
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_dbl < "1010000" then
track_dbl <= std_logic_vector(unsigned(track_dbl) + 1);
end if;
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_dbl > "0000001" then
track_dbl <= std_logic_vector(unsigned(track_dbl) - 1);
end if;
end if;
end if;
end if;
end if;
end process;
sd_spi : entity work.spi_controller
port map
(
CS_N => sd_dat3, --: out std_logic; -- MMC chip select
MOSI => sd_cmd, --: out std_logic; -- Data to card (master out slave in)
MISO => sd_dat, --: in std_logic; -- Data from card (master in slave out)
SCLK => sd_clk, --: out std_logic; -- Card clock
ram_write_addr => ram_write_addr, --: out unsigned(13 downto 0);
ram_di => ram_di, --: out unsigned(7 downto 0);
ram_we => ram_we,
change => disk_change,
track => unsigned(track_dbl(6 downto 1)),
image => unsigned(disk_num),
CLK_14M => clk18,
reset => reset,
busy => sd_busy
);
track_buffer : entity work.gen_ram
generic map
(
dWidth => 8,
aWidth => 13
)
port map
(
clk => not clk18,
we => ram_we,
addr => ram_addr,
d => ram_di,
q => ram_do
);
with sd_busy select
-- ram_addr <= ram_write_addr when '1', unsigned('0'&track_read_adr) when others;
ram_addr <= ram_write_addr when '1', unsigned(track_read_adr) when others;
led(0) <= mode; -- read/write
led(2 downto 1) <= stp; -- stepper motor control
led(3) <= mtr; -- stepper motor on/off
led(5 downto 4) <= freq; -- motor frequency
led(6) <= act; -- activity LED
led(7) <= sd_busy; -- SD read
end struct;

View File

@@ -30,7 +30,7 @@
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module C16(
module C16 #(parameter MODE_PAL = 1)(
input wire CLK28,
input wire RESET,
input wire WAIT,
@@ -150,7 +150,7 @@ ted mos8360(
// Kernal rom
kernal_rom kernal(
kernal_rom #(.MODE_PAL(MODE_PAL)) kernal(
.clk(CLK28),
.address_in(sreset?kernal_dl_addr:c16_addr[13:0]),
.data_out(kernal_data),

View File

@@ -167,7 +167,7 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# SignalTap II Assignments
# ========================
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE stp1.stp
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp
# Power Estimation Assignments
# ============================
@@ -321,14 +321,9 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to CONF_DATA0
set_global_assignment -name VERILOG_FILE sd_card.v
set_global_assignment -name VHDL_FILE spi_controller.vhd
set_global_assignment -name VHDL_FILE rom_C1541.vhd
set_global_assignment -name VHDL_FILE m6522.vhd
set_global_assignment -name VERILOG_INPUT_VERSION VERILOG_2001
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name VHDL_FILE gen_ram.vhd
set_global_assignment -name VHDL_FILE gcr_floppy.vhd
set_global_assignment -name VHDL_FILE c1541_sd.vhd
set_global_assignment -name VHDL_FILE c1541_logic.vhd
set_global_assignment -name QIP_FILE pll_ntsc.qip
set_global_assignment -name QIP_FILE pll_pal.qip
set_global_assignment -name VERILOG_FILE data_io.v
@@ -348,4 +343,16 @@ set_global_assignment -name VERILOG_FILE c16_keymatrix.v
set_global_assignment -name VERILOG_FILE c16.v
set_global_assignment -name VERILOG_FILE basic_rom.v
set_global_assignment -name SIGNALTAP_FILE stp1.stp
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
set_global_assignment -name VHDL_FILE c1541/m6522.vhd
set_global_assignment -name VHDL_FILE c1541/gcr_floppy.vhd
set_global_assignment -name VHDL_FILE c1541/spram.vhd
set_global_assignment -name VHDL_FILE c1541/sprom.vhd
set_global_assignment -name VHDL_FILE c1541/c1541_sd.vhd
set_global_assignment -name VHDL_FILE c1541/c1541_logic.vhd
set_global_assignment -name SYSTEMVERILOG_FILE c1541/mist_sd_card.sv
set_global_assignment -name VHDL_FILE t65/T65_Pack.vhd
set_global_assignment -name VHDL_FILE t65/T65_MCode.vhd
set_global_assignment -name VHDL_FILE t65/T65_ALU.vhd
set_global_assignment -name VHDL_FILE t65/T65.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

52
cores/c16/c16_mist.sdc Normal file
View File

@@ -0,0 +1,52 @@
#************************************************************
# THIS IS A WIZARD-GENERATED FILE.
#
# Version 13.1.4 Build 182 03/12/2014 SJ Full Version
#
#************************************************************
# Copyright (C) 1991-2014 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
# Clock constraints
create_clock -name "CLOCK_27" -period 37.037 [get_ports {CLOCK_27}]
create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}]
# Automatically constrain PLL and other generated clocks
derive_pll_clocks -create_base_clocks
# Automatically calculate clock uncertainty to jitter and other effects.
derive_clock_uncertainty
# Clock groups
set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[*]}]
# Some relaxed constrain to the VGA pins. The signals should arrive together, the delay is not really important.
set_output_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -max 0 [get_ports {VGA_*}]
set_output_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -min -5 [get_ports {VGA_*}]
# SDRAM delays
set_input_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -max 6.4 [get_ports SDRAM_DQ[*]]
set_input_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -min 3.2 [get_ports SDRAM_DQ[*]]
set_output_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -max 1.5 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
set_output_delay -clock [get_clocks {pll_pal|altpll_component|auto_generated|pll1|clk[0]}] -min -0.8 [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
set_false_path -to [get_ports {AUDIO_L}]
set_false_path -to [get_ports {AUDIO_R}]
set_false_path -to [get_ports {LED}]

View File

@@ -57,6 +57,7 @@ module c16_mist (
output [5:0] VGA_B
);
parameter MODE_PAL = 1'b1;
// -------------------------------------------------------------------------
// ------------------------------ user_io ----------------------------------
// -------------------------------------------------------------------------
@@ -70,14 +71,14 @@ module c16_mist (
// it to control the menu on the OSD
parameter CONF_STR = {
"C16;PRG;",
"S1,D64;",
"S,D64,Mount Disk;",
"O2,Scanlines,Off,On;",
"O3,Joysticks,Normal,Swapped;",
"O4,Memory,64k,16k;",
"T5,Reset"
"T5,Reset;"
};
parameter CONF_STR_LEN = 8+7+20+28+18+8;
parameter CONF_STR_LEN = 8+17+20+28+18+9;
// the status register is controlled by the on screen display (OSD)
wire [7:0] status;
@@ -210,22 +211,26 @@ always @(posedge clk28) begin
end
// signals to connect io controller with virtual sd card
wire [32:0] sd_lba;
wire [31:0] sd_lba;
wire sd_rd;
wire sd_wr;
wire sd_ack;
wire sd_ack_conf;
wire sd_conf;
wire sd_sdhc;
wire sd_sdhc = 1'b1;
wire [7:0] sd_dout;
wire sd_dout_strobe;
wire [7:0] sd_din;
wire sd_din_strobe;
wire sd_change;
wire img_mounted;
wire [8:0] sd_buff_addr;
// include user_io module for arm controller communication
user_io #(.STRLEN(CONF_STR_LEN)) user_io (
.conf_str ( CONF_STR ),
.clk_sys ( clk28 ),
.SPI_CLK ( SPI_SCK ),
.SPI_SS_IO ( CONF_DATA0 ),
.SPI_MISO ( SPI_DO ),
@@ -248,44 +253,24 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io (
.sd_rd ( sd_rd ),
.sd_wr ( sd_wr ),
.sd_ack ( sd_ack ),
.sd_ack_conf ( sd_ack_conf ),
.sd_conf ( sd_conf ),
.sd_sdhc ( sd_sdhc ),
.sd_dout ( sd_dout ),
.sd_dout_strobe ( sd_dout_strobe ),
.sd_din ( sd_din ),
.sd_din_strobe ( sd_din_strobe ),
.sd_change ( sd_change ),
.sd_buff_addr ( sd_buff_addr),
.img_mounted ( img_mounted ),
.status ( status )
);
wire sd_cs;
wire sd_dat;
wire sd_dat3;
wire sd_cmd;
wire sd_clk;
sd_card sd_card (
// connection to io controller
.io_lba ( sd_lba ),
.io_rd ( sd_rd ),
.io_wr ( sd_wr ),
.io_ack ( sd_ack ),
.io_conf ( sd_conf ),
.io_sdhc ( sd_sdhc ),
.io_din ( sd_dout ),
.io_din_strobe ( sd_dout_strobe ),
.io_dout ( sd_din ),
.io_dout_strobe ( sd_din_strobe ),
.allow_sdhc ( 1'b1 ),
// connection to host
.sd_cs ( sd_dat3 ),
.sd_sck ( sd_clk ),
.sd_sdi ( sd_cmd ),
.sd_sdo ( sd_dat )
);
// ---------------------------------------------------------------------------------
// ------------------------------ prg memory injection -----------------------------
// ---------------------------------------------------------------------------------
@@ -518,7 +503,7 @@ always @(negedge clk28) begin
end
// include the c16 itself
C16 c16 (
C16 #(.MODE_PAL(MODE_PAL)) c16 (
.CLK28 ( clk28 ),
.RESET ( reset ),
.WAIT ( c16_wait ),
@@ -569,9 +554,9 @@ C16 c16 (
// the FPGATED uses two different clocks for NTSC and PAL mode.
// Switching the clocks may crash the system. We might need to force a reset it.
wire clk28 = c16_pal?clk28_pal:clk28_ntsc;
wire clk28 = MODE_PAL?clk28_pal:clk28_ntsc;
wire pll_locked = pll_pal_locked && pll_ntsc_locked;
// tv15hkz has quarter the pixel rate, so we need a 7mhz clock for the OSD
reg clk7;
always @(posedge clk14)
@@ -621,18 +606,12 @@ wire c1541_iec_atn_i = c16_iec_atn_i;
wire c1541_iec_data_i = c16_iec_data_i;
wire c1541_iec_clk_i = c16_iec_clk_i;
c1541_sd c1541_sd (
.clk32 ( clk32 ),
.clk18 ( clk28 ), // MiST uses virtual SPI SD, so any clock can be used.
.clk32 ( clk28 ),
.reset ( reset ),
.c1541rom_addr ( 14'h0000 ),
.c1541rom_data ( 8'h00 ),
.c1541rom_wr ( 1'b0 ),
.disk_change ( sd_change ),
.disk_num ( 10'd0 ), // not seletable by f8 or similar
.disk_change ( img_mounted ),
.disk_num ( 10'd0 ), // always 0 on MiST, the image is selected by the OSD menu
.iec_atn_i ( c1541_iec_atn_i ),
.iec_data_i ( c1541_iec_data_i ),
@@ -642,12 +621,16 @@ c1541_sd c1541_sd (
.iec_data_o ( c1541_iec_data_o ),
.iec_clk_o ( c1541_iec_clk_o ),
.sd_dat ( sd_dat ),
.sd_dat3 ( sd_dat3 ),
.sd_cmd ( sd_cmd ),
.sd_clk ( sd_clk ),
.sd_lba ( sd_lba ),
.sd_rd ( sd_rd ),
.sd_wr ( sd_wr ),
.sd_ack ( sd_ack ),
.sd_buff_din ( sd_din ),
.sd_buff_dout ( sd_dout ),
.sd_buff_wr ( sd_dout_strobe ),
.sd_buff_addr ( sd_buff_addr ),
.led ( led_disk )
// .led ( led_disk )
);
endmodule

View File

@@ -1,221 +0,0 @@
---------------------------------------------------------------------------------
-- Commodore 1541 gcr floppy (read only) by Dar (darfpga@aol.fr) 02-April-2015
-- 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
--
-- 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;
do : out std_logic_vector(7 downto 0); -- disk read data
mode : in std_logic; -- read/write
stp : in std_logic_vector(1 downto 0); -- stepper motor control
mtr : in std_logic; -- stepper motor on/off
freq : in std_logic_vector(1 downto 0); -- motor (gcr_bit) frequency
sync_n : out std_logic; -- reading SYNC bytes
byte_n : out std_logic; -- byte ready
track : in std_logic_vector(5 downto 0);
track_adr : out std_logic_vector(12 downto 0);
track_data : in std_logic_vector(7 downto 0);
track_ready : in std_logic;
dbg_sector : out std_logic_vector(4 downto 0)
);
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 : 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);
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);
begin
sync_n <= sync_in_n when mtr = '1' and track_ready = '1' else '1';
dbg_sector <= sector;
with byte_cnt select
data_header <=
X"08" when "000000000",
"00"&track xor "000"&sector when "000000001",
"000"&sector 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",
track_data 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" ;
process (clk32)
variable bit_clk_cnt : std_logic_vector(7 downto 0) := (others => '0');
begin
if rising_edge(clk32) then
bit_clk_en <= '0';
if bit_clk_cnt = X"6F" then
bit_clk_en <= '1';
bit_clk_cnt := (others => '0');
else
bit_clk_cnt := std_logic_vector(unsigned(bit_clk_cnt) + 1);
end if;
byte_n <= '1';
if byte_in_n = '0' and mtr = '1' and track_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 process;
process (clk32, bit_clk_en)
begin
if rising_edge(clk32) and bit_clk_en = '1' then
if sync_in_n = '0' then
byte_cnt <= (others => '0');
nibble <= '0';
gcr_bit_cnt <= (others => '0');
bit_cnt <= (others => '0');
do <= (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 <= std_logic_vector(unsigned(sync_cnt +1));
end if;
else
gcr_bit_cnt <= std_logic_vector(unsigned(gcr_bit_cnt)+1);
if gcr_bit_cnt = X"4" then
gcr_bit_cnt <= (others => '0');
if nibble = '1' then
nibble <= '0';
track_adr <= sector & byte_cnt(7 downto 0);
if byte_cnt = "000000000" then
data_cks <= (others => '0');
else
data_cks <= data_cks xor data;
end if;
byte_cnt <= std_logic_vector(unsigned(byte_cnt)+1);
else
nibble <= '1';
end if;
end if;
bit_cnt <= std_logic_vector(unsigned(bit_cnt)+1);
byte_in_n <= '1';
if bit_cnt = X"7" then
byte_in_n <= '0';
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 = sector_max then
sector <= (others=>'0');
else
sector <= std_logic_vector(unsigned(sector)+1);
end if;
end if;
end if;
gcr_byte <= gcr_byte(6 downto 0) & gcr_bit;
if bit_cnt = X"7" then
do <= gcr_byte(6 downto 0) & gcr_bit;
end if;
end if;
end if;
end process;
end struct;

View File

@@ -29,8 +29,8 @@
// If you want to convert your own kernal image to compatible version use
// bin2hex.pl perl script to convert it to .hex format.
//////////////////////////////////////////////////////////////////////////////////
module kernal_rom(
input wire clk,
module kernal_rom #(parameter MODE_PAL=1) (
input wire clk,
input wire [13:0] address_in,
output wire [7:0] data_out,
input wire [7:0] data_in,
@@ -50,10 +50,11 @@ initial begin
//$readmemh("Diag264_PAL.hex",kernal);
//$readmemh("Diag264_NTSC.hex",kernal);
if (MODE_PAL)
$readmemh("roms/kernal_PAL.hex",kernal);
else
$readmemh("roms/kernal_NTSC.hex",kernal);
$readmemh("kernal_PAL.hex",kernal);
//$readmemh("kernal_NTSC.hex",kernal);
//$readmemh("Jiffy_PAL.hex",kernal);
// Note that Jiffy DOS is not free so Jiffy_PAL.hex is not included with FPGATED source code

View File

@@ -1,198 +0,0 @@
-- megafunction wizard: %RAM: 2-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: rom_C1541.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.1.4 Build 182 03/12/2014 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2014 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY rom_C1541 IS
PORT
(
clock : IN STD_LOGIC := '1';
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdaddress : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
wraddress : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
wren : IN STD_LOGIC := '0';
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END rom_C1541;
ARCHITECTURE SYN OF rom_c1541 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
q <= sub_wire0(7 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_b => "NONE",
address_reg_b => "CLOCK0",
clock_enable_input_a => "BYPASS",
clock_enable_input_b => "BYPASS",
clock_enable_output_b => "BYPASS",
init_file => "std_C1541.mif",
intended_device_family => "Cyclone III",
lpm_type => "altsyncram",
numwords_a => 16384,
numwords_b => 16384,
operation_mode => "DUAL_PORT",
outdata_aclr_b => "NONE",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_mixed_ports => "DONT_CARE",
widthad_a => 14,
widthad_b => 14,
width_a => 8,
width_b => 8,
width_byteena_a => 1
)
PORT MAP (
address_a => wraddress,
clock0 => clock,
data_a => data,
wren_a => wren,
address_b => rdaddress,
q_b => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
-- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
-- Retrieval info: PRIVATE: CLRdata NUMERIC "0"
-- Retrieval info: PRIVATE: CLRq NUMERIC "0"
-- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
-- Retrieval info: PRIVATE: CLRrren NUMERIC "0"
-- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
-- Retrieval info: PRIVATE: CLRwren NUMERIC "0"
-- Retrieval info: PRIVATE: Clock NUMERIC "0"
-- Retrieval info: PRIVATE: Clock_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clock_B NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MEMSIZE NUMERIC "131072"
-- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
-- Retrieval info: PRIVATE: MIFfilename STRING "std_C1541.mif"
-- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2"
-- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
-- Retrieval info: PRIVATE: REGdata NUMERIC "1"
-- Retrieval info: PRIVATE: REGq NUMERIC "1"
-- Retrieval info: PRIVATE: REGrdaddress NUMERIC "1"
-- Retrieval info: PRIVATE: REGrren NUMERIC "1"
-- Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
-- Retrieval info: PRIVATE: REGwren NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
-- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
-- Retrieval info: PRIVATE: VarWidth NUMERIC "0"
-- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
-- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8"
-- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
-- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8"
-- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0"
-- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
-- Retrieval info: PRIVATE: enable NUMERIC "0"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE"
-- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
-- Retrieval info: CONSTANT: INIT_FILE STRING "std_C1541.mif"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "16384"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
-- Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14"
-- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "14"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_B NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
-- Retrieval info: USED_PORT: rdaddress 0 0 14 0 INPUT NODEFVAL "rdaddress[13..0]"
-- Retrieval info: USED_PORT: wraddress 0 0 14 0 INPUT NODEFVAL "wraddress[13..0]"
-- Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren"
-- Retrieval info: CONNECT: @address_a 0 0 14 0 wraddress 0 0 14 0
-- Retrieval info: CONNECT: @address_b 0 0 14 0 rdaddress 0 0 14 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q_b 0 0 8 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL rom_C1541.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL rom_C1541.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL rom_C1541.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL rom_C1541.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL rom_C1541_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

File diff suppressed because it is too large Load Diff

16384
cores/c16/roms/kernal_NTSC.hex Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,473 +0,0 @@
//
// sd_card.v
//
// This file implelents a sd card for the MIST board since on the board
// the SD card is connected to the ARM IO controller and the FPGA has no
// direct connection to the SD card. This file provides a SD card like
// interface to the IO controller easing porting of cores that expect
// a direct interface to the SD card.
//
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
//
// 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/>.
//
// http://elm-chan.org/docs/mmc/mmc_e.html
module sd_card (
// link to user_io for io controller
output [31:0] io_lba,
output reg io_rd,
output reg io_wr,
input io_ack,
output io_conf,
output io_sdhc,
// data coming in from io controller
input [7:0] io_din,
input io_din_strobe,
// data going out to io controller
output [7:0] io_dout,
input io_dout_strobe,
// configuration input
input allow_sdhc,
input sd_cs,
input sd_sck,
input sd_sdi,
output reg sd_sdo
);
// set io_rd once read_state machine starts waiting (rising edge of req_io_rd)
// and clear it once io controller uploads something (io_ack==1)
reg req_io_rd = 1'b0; // set when write_state is changed to RD_STATE_WAIT_IO
always @(posedge req_io_rd or posedge io_ack) begin
if(io_ack) io_rd <= 1'b0;
else io_rd <= 1'b1;
end
reg req_io_wr = 1'b0; // set when write_state is changed to WR_STATE_BUSY
always @(posedge req_io_wr or posedge io_ack) begin
if(io_ack) io_wr <= 1'b0;
else io_wr <= 1'b1;
end
wire [31:0] OCR = { 1'b0, io_sdhc, 30'h0 }; // bit30 = 1 -> high capaciry card (sdhc)
wire [7:0] READ_DATA_TOKEN = 8'hfe;
// number of bytes to wait after a command before sending the reply
localparam NCR=4;
localparam RD_STATE_IDLE = 2'd0;
localparam RD_STATE_WAIT_IO = 2'd1;
localparam RD_STATE_SEND_TOKEN = 2'd2;
localparam RD_STATE_SEND_DATA = 2'd3;
reg [1:0] read_state = RD_STATE_IDLE;
localparam WR_STATE_IDLE = 3'd0;
localparam WR_STATE_EXP_DTOKEN = 3'd1;
localparam WR_STATE_RECV_DATA = 3'd2;
localparam WR_STATE_RECV_CRC0 = 3'd3;
localparam WR_STATE_RECV_CRC1 = 3'd4;
localparam WR_STATE_SEND_DRESP = 3'd5;
localparam WR_STATE_BUSY = 3'd6;
reg [2:0] write_state = WR_STATE_IDLE;
reg card_is_reset = 1'b0; // flag that card has received a reset command
reg [6:0] sbuf;
reg cmd55;
reg new_cmd_rcvd;
reg [7:0] cmd = 8'h00;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [3:0] byte_cnt= 4'd15; // counts bytes
reg [31:0] lba;
assign io_lba = io_sdhc?lba:{9'd0, lba[31:9]};
reg [7:0] reply;
reg [7:0] reply0, reply1, reply2, reply3;
reg [3:0] reply_len;
// falling edge of io_ack signals that a sector to be read has been written into
// the sector buffer by the io controller. This signal is kept set as long
// as the read state machine is in the "wait for io controller" state (state 1)
wire rd_wait_io = (read_state != RD_STATE_IDLE);
reg rd_io_ack_i = 1'b0;
always @(negedge io_ack or negedge rd_wait_io) begin
if(!rd_wait_io) rd_io_ack_i <= 1'b0;
else rd_io_ack_i <= 1'b1;
end
wire wr_wait_io = (write_state == WR_STATE_BUSY);
reg wr_io_ack_i = 1'b0;
always @(negedge io_ack or negedge wr_wait_io) begin
if(!wr_wait_io) wr_io_ack_i <= 1'b0;
else wr_io_ack_i <= 1'b1;
end
// bring xx_io_ack into sd cards clock domain
reg wr_io_ack;
reg rd_io_ack;
always @(posedge sd_sck) begin
rd_io_ack <= rd_io_ack_i;
wr_io_ack <= wr_io_ack_i;
end
// ------------------------- SECTOR BUFFER -----------------------
// the buffer itself. Can hold one sector
// (* ramstyle = "logic" *) reg [7:0] buffer [511:0];
reg [7:0] buffer [511:0];
// ---------------- buffer read engine -----------------------
reg [8:0] buffer_rptr;
reg buffer_read_strobe;
wire buffer_dout_strobe = buffer_read_strobe || io_dout_strobe;
reg [7:0] buffer_dout;
assign io_dout = buffer_dout;
// buffer_rptr is increased in a diferent clock domain than it's
// evaluated. These single bit registers bring certain states from
// one domain into the other one in a safe (atomic) way
reg buffer_read_sector_done;
reg buffer_read_ciscid_done;
always @(posedge buffer_dout_strobe or posedge new_cmd_rcvd) begin
if(new_cmd_rcvd == 1) begin
buffer_rptr <= 9'd0;
buffer_read_sector_done <= 1'b0;
buffer_read_ciscid_done <= 1'b0;
end else begin
buffer_dout <= buffer[buffer_rptr];
buffer_rptr <= buffer_rptr + 9'd1;
if(buffer_rptr == 511) buffer_read_sector_done <= 1'b1;
if(buffer_rptr == 15) buffer_read_ciscid_done <= 1'b1;
end
end
// ---------------- buffer write engine -----------------------
reg [8:0] buffer_wptr;
reg buffer_write_strobe;
wire buffer_din_strobe = io_din_strobe || buffer_write_strobe;
wire [7:0] buffer_din = (cmd == 8'h51)?io_din:{sbuf, sd_sdi};
always @(posedge buffer_din_strobe or posedge new_cmd_rcvd) begin
if(new_cmd_rcvd == 1)
buffer_wptr <= 9'd0;
else begin
buffer[buffer_wptr] <= buffer_din;
buffer_wptr <= buffer_wptr + 9'd1;
end
end
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;
// ------------------------- CSD/CID BUFFER ----------------------
assign io_conf = (csd_wptr == 0); // csd_wptr still 0 -> configuration required
// the 32 bytes as sent from the io controller
reg [7:0] cid [15:0] /* synthesis ramstyle = "logic" */;
reg [7:0] csd [15:0] /* synthesis ramstyle = "logic" */;
reg [7:0] conf;
reg [7:0] cid_byte;
reg [7:0] csd_byte;
reg [5:0] csd_wptr = 6'd0;
// conf[0]==1 -> io controller is using an sdhc card
wire io_has_sdhc = conf[0];
assign io_sdhc = allow_sdhc && io_has_sdhc;
always @(posedge io_din_strobe) begin
// if io controller sends data without asserting io_ack, then it's
// updating the config
if(!io_ack && (csd_wptr <= 32)) begin
if(csd_wptr < 16) // first 16 bytes are cid
cid[csd_wptr[3:0]] <= io_din;
if((csd_wptr >= 16) && (csd_wptr < 32)) // then comes csd
csd[csd_wptr[3:0]] <= io_din;
if(csd_wptr == 32) // finally a config byte
conf <= io_din;
csd_wptr <= csd_wptr + 6'd1;
end
end
always @(posedge buffer_dout_strobe) begin
cid_byte <= cid[buffer_rptr[3:0]];
csd_byte <= csd[buffer_rptr[3:0]];
end
// ----------------- spi transmitter --------------------
// advance transmitter state machine on falling sck edge, so data is valid on the
// rising edge
always@(negedge sd_sck) begin
if(sd_cs == 0) begin
buffer_read_strobe <= 1'b0;
sd_sdo <= 1'b1; // default: send 1's (busy/wait)
req_io_rd <= 1'b0;
if(byte_cnt == 5+NCR) begin
sd_sdo <= reply[~bit_cnt];
if(bit_cnt == 7) begin
// these three commands all have a reply_len of 0 and will thus
// not send more than a single reply byte
// CMD9: SEND_CSD
// CMD10: SEND_CID
if((cmd == 8'h49)||(cmd == 8'h4a))
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
// CMD17: READ_SINGLE_BLOCK
if(cmd == 8'h51) begin
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
req_io_rd <= 1'b1; // trigger request to io controller
end
end
end
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
sd_sdo <= reply0[~bit_cnt];
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
sd_sdo <= reply1[~bit_cnt];
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
sd_sdo <= reply2[~bit_cnt];
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
sd_sdo <= reply3[~bit_cnt];
else
sd_sdo <= 1'b1;
// ---------- read state machine processing -------------
case(read_state)
RD_STATE_IDLE: ;
// don't do anything
// waiting for io controller to return data
RD_STATE_WAIT_IO: begin
if(rd_io_ack && (bit_cnt == 7))
read_state <= RD_STATE_SEND_TOKEN;
end
// send data token
RD_STATE_SEND_TOKEN: begin
sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
if(bit_cnt == 7) begin
read_state <= RD_STATE_SEND_DATA; // next: send data
buffer_read_strobe <= 1'b1; // trigger read of first data byte
end
end
// send data
RD_STATE_SEND_DATA: begin
if(cmd == 8'h51) // CMD17: READ_SINGLE_BLOCK
sd_sdo <= buffer_dout[~bit_cnt];
else if(cmd == 8'h49) // CMD9: SEND_CSD
sd_sdo <= csd_byte[~bit_cnt];
else if(cmd == 8'h4a) // CMD10: SEND_CID
sd_sdo <= cid_byte[~bit_cnt];
else
sd_sdo <= 1'b1;
if(bit_cnt == 7) begin
// sent 512 sector data bytes?
if((cmd == 8'h51) && buffer_read_sector_done) // (buffer_rptr == 0))
read_state <= RD_STATE_IDLE; // next: send crc. It's ignored so return to idle state
// sent 16 cid/csd data bytes?
else if(((cmd == 8'h49)||(cmd == 8'h4a)) && buffer_read_ciscid_done) // && (buffer_rptr == 16))
read_state <= RD_STATE_IDLE; // return to idle state
else
buffer_read_strobe <= 1'b1; // not done yet -> trigger read of next data byte
end
end
endcase
// ------------------ write support ----------------------
// send write data response
if(write_state == WR_STATE_SEND_DRESP)
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
// busy after write until the io controller sends ack
if(write_state == WR_STATE_BUSY)
sd_sdo <= 1'b0;
end
end
// spi receiver
always @(posedge sd_sck or posedge sd_cs) begin
// cs is active low
if(sd_cs == 1) begin
bit_cnt <= 3'd0;
end else begin
new_cmd_rcvd <= 1'b0;
buffer_write_strobe <= 1'b0;
req_io_wr <= 1'b0;
bit_cnt <= bit_cnt + 3'd1;
// assemble byte
if(bit_cnt != 7)
sbuf[6:0] <= { sbuf[5:0], sd_sdi };
else begin
// finished reading one byte
// byte counter runs against 15 byte boundary
if(byte_cnt != 15)
byte_cnt <= byte_cnt + 4'd1;
// byte_cnt > 6 -> complete command received
// first byte of valid command is 01xxxxxx
// don't accept new commands once a write or read command has been accepted
if((byte_cnt > 5) && (write_state == WR_STATE_IDLE) &&
(read_state == RD_STATE_IDLE) && sbuf[6:5] == 2'b01) begin
byte_cnt <= 4'd0;
cmd <= { sbuf, sd_sdi};
new_cmd_rcvd <= 1'b1;
// set cmd55 flag if previous command was 55
cmd55 <= (cmd == 8'h77);
end
// parse additional command bytes
if(byte_cnt == 0) lba[31:24] <= { sbuf, sd_sdi};
if(byte_cnt == 1) lba[23:16] <= { sbuf, sd_sdi};
if(byte_cnt == 2) lba[15:8] <= { sbuf, sd_sdi};
if(byte_cnt == 3) lba[7:0] <= { sbuf, sd_sdi};
// last byte received, evaluate
if(byte_cnt == 4) begin
// default:
reply <= 8'h04; // illegal command
reply_len <= 4'd0; // no extra reply bytes
// CMD0: GO_IDLE_STATE
if(cmd == 8'h40) begin
card_is_reset <= 1'b1;
reply <= 8'h01; // ok, busy
end
// every other command is only accepted after a reset
else if(card_is_reset) begin
// CMD1: SEND_OP_COND
if(cmd == 8'h41)
reply <= 8'h00; // ok, not busy
// CMD8: SEND_IF_COND (V2 only)
else if(cmd == 8'h48) begin
reply <= 8'h01; // ok, busy
reply0 <= 8'h00;
reply1 <= 8'h00;
reply2 <= 8'h01;
reply3 <= 8'hAA;
reply_len <= 4'd4;
end
// CMD9: SEND_CSD
else if(cmd == 8'h49)
reply <= 8'h00; // ok
// CMD10: SEND_CID
else if(cmd == 8'h4a)
reply <= 8'h00; // ok
// CMD16: SET_BLOCKLEN
else if(cmd == 8'h50) begin
// we only support a block size of 512
if(lba == 32'd512)
reply <= 8'h00; // ok
else
reply <= 8'h40; // parmeter error
end
// CMD17: READ_SINGLE_BLOCK
else if(cmd == 8'h51)
reply <= 8'h00; // ok
// CMD24: WRITE_BLOCK
else if(cmd == 8'h58) begin
reply <= 8'h00; // ok
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
end
// ACMD41: APP_SEND_OP_COND
else if(cmd55 && (cmd == 8'h69))
reply <= 8'h00; // ok, not busy
// CMD55: APP_COND
else if(cmd == 8'h77)
reply <= 8'h01; // ok, busy
// CMD58: READ_OCR
else if(cmd == 8'h7a) begin
reply <= 8'h00; // ok
reply0 <= OCR[31:24]; // bit 30 = 1 -> high capacity card
reply1 <= OCR[23:16];
reply2 <= OCR[15:8];
reply3 <= OCR[7:0];
reply_len <= 4'd4;
end
end
end
// ---------- handle write -----------
case(write_state)
// don't do anything in idle state
WR_STATE_IDLE: ;
// waiting for data token
WR_STATE_EXP_DTOKEN:
if({ sbuf, sd_sdi} == 8'hfe )
write_state <= WR_STATE_RECV_DATA;
// transfer 512 bytes
WR_STATE_RECV_DATA: begin
// push one byte into local buffer
buffer_write_strobe <= 1'b1;
// all bytes written?
if(buffer_wptr == 511)
write_state <= WR_STATE_RECV_CRC0;
end
// transfer 1st crc byte
WR_STATE_RECV_CRC0:
write_state <= WR_STATE_RECV_CRC1;
// transfer 2nd crc byte
WR_STATE_RECV_CRC1:
write_state <= WR_STATE_SEND_DRESP;
// send data response
WR_STATE_SEND_DRESP: begin
write_state <= WR_STATE_BUSY;
req_io_wr <= 1'b1; // trigger write request to io ontroller
end
// wait for io controller to accept data
WR_STATE_BUSY:
if(wr_io_ack)
write_state <= WR_STATE_IDLE;
default:;
endcase
end
end
end
endmodule

564
cores/c16/t65/T65.vhd Normal file
View File

@@ -0,0 +1,564 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 301 more merging
-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- 65xx compatible microprocessor core
--
-- Version : 0246
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t65/
--
-- Limitations :
--
-- 65C02 and 65C816 modes are incomplete
-- Undocumented instructions are not supported
-- Some interface signals behaves incorrect
--
-- File history :
--
-- 0246 : First release
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T65_Pack.all;
-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
-- the ready signal to limit the CPU.
entity T65 is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
Res_n : in std_logic;
Enable : in std_logic;
Clk : in std_logic;
Rdy : in std_logic;
Abort_n : in std_logic;
IRQ_n : in std_logic;
NMI_n : in std_logic;
SO_n : in std_logic;
R_W_n : out std_logic;
Sync : out std_logic;
EF : out std_logic;
MF : out std_logic;
XF : out std_logic;
ML_n : out std_logic;
VP_n : out std_logic;
VDA : out std_logic;
VPA : out std_logic;
A : out std_logic_vector(23 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T65;
architecture rtl of T65 is
-- Registers
signal ABC, X, Y, D : std_logic_vector(15 downto 0);
signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
signal BAH : std_logic_vector(7 downto 0);
signal BAL : std_logic_vector(8 downto 0);
signal PBR : std_logic_vector(7 downto 0);
signal DBR : std_logic_vector(7 downto 0);
signal PC : unsigned(15 downto 0);
signal S : unsigned(15 downto 0);
signal EF_i : std_logic;
signal MF_i : std_logic;
signal XF_i : std_logic;
signal IR : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal Mode_r : std_logic_vector(1 downto 0);
signal ALU_Op_r : std_logic_vector(3 downto 0);
signal Write_Data_r : std_logic_vector(2 downto 0);
signal Set_Addr_To_r : std_logic_vector(1 downto 0);
signal PCAdder : unsigned(8 downto 0);
signal RstCycle : std_logic;
signal IRQCycle : std_logic;
signal NMICycle : std_logic;
signal B_o : std_logic;
signal SO_n_o : std_logic;
signal IRQ_n_o : std_logic;
signal NMI_n_o : std_logic;
signal NMIAct : std_logic;
signal Break : std_logic;
-- ALU signals
signal BusA : std_logic_vector(7 downto 0);
signal BusA_r : std_logic_vector(7 downto 0);
signal BusB : std_logic_vector(7 downto 0);
signal ALU_Q : std_logic_vector(7 downto 0);
signal P_Out : std_logic_vector(7 downto 0);
-- Micro code outputs
signal LCycle : std_logic_vector(2 downto 0);
signal ALU_Op : std_logic_vector(3 downto 0);
signal Set_BusA_To : std_logic_vector(2 downto 0);
signal Set_Addr_To : std_logic_vector(1 downto 0);
signal Write_Data : std_logic_vector(2 downto 0);
signal Jump : std_logic_vector(1 downto 0);
signal BAAdd : std_logic_vector(1 downto 0);
signal BreakAtNA : std_logic;
signal ADAdd : std_logic;
signal AddY : std_logic;
signal PCAdd : std_logic;
signal Inc_S : std_logic;
signal Dec_S : std_logic;
signal LDA : std_logic;
signal LDP : std_logic;
signal LDX : std_logic;
signal LDY : std_logic;
signal LDS : std_logic;
signal LDDI : std_logic;
signal LDALU : std_logic;
signal LDAD : std_logic;
signal LDBAL : std_logic;
signal LDBAH : std_logic;
signal SaveP : std_logic;
signal Write : std_logic;
signal really_rdy : std_logic;
signal R_W_n_i : std_logic;
begin
-- ehenciak : gate Rdy with read/write to make an "OK, it's
-- really OK to stop the processor now if Rdy is
-- deasserted" signal
really_rdy <= Rdy or not(R_W_n_i);
-- ehenciak : Drive R_W_n_i off chip.
R_W_n <= R_W_n_i;
Sync <= '1' when MCycle = "000" else '0';
EF <= EF_i;
MF <= MF_i;
XF <= XF_i;
ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!!
VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
mcode : T65_MCode
port map(
Mode => Mode_r,
IR => IR,
MCycle => MCycle,
P => P,
LCycle => LCycle,
ALU_Op => ALU_Op,
Set_BusA_To => Set_BusA_To,
Set_Addr_To => Set_Addr_To,
Write_Data => Write_Data,
Jump => Jump,
BAAdd => BAAdd,
BreakAtNA => BreakAtNA,
ADAdd => ADAdd,
AddY => AddY,
PCAdd => PCAdd,
Inc_S => Inc_S,
Dec_S => Dec_S,
LDA => LDA,
LDP => LDP,
LDX => LDX,
LDY => LDY,
LDS => LDS,
LDDI => LDDI,
LDALU => LDALU,
LDAD => LDAD,
LDBAL => LDBAL,
LDBAH => LDBAH,
SaveP => SaveP,
Write => Write
);
alu : T65_ALU
port map(
Mode => Mode_r,
Op => ALU_Op_r,
BusA => BusA_r,
BusB => BusB,
P_In => P,
P_Out => P_Out,
Q => ALU_Q
);
process (Res_n, Clk)
begin
if Res_n = '0' then
PC <= (others => '0'); -- Program Counter
IR <= "00000000";
S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
D <= (others => '0');
PBR <= (others => '0');
DBR <= (others => '0');
Mode_r <= (others => '0');
ALU_Op_r <= "1100";
Write_Data_r <= "000";
Set_Addr_To_r <= "00";
R_W_n_i <= '1';
EF_i <= '1';
MF_i <= '1';
XF_i <= '1';
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
if (really_rdy = '1') then
R_W_n_i <= not Write or RstCycle;
D <= (others => '1'); -- Dummy
PBR <= (others => '1'); -- Dummy
DBR <= (others => '1'); -- Dummy
EF_i <= '0'; -- Dummy
MF_i <= '0'; -- Dummy
XF_i <= '0'; -- Dummy
if MCycle = "000" then
Mode_r <= Mode;
if IRQCycle = '0' and NMICycle = '0' then
PC <= PC + 1;
end if;
if IRQCycle = '1' or NMICycle = '1' then
IR <= "00000000";
else
IR <= DI;
end if;
end if;
ALU_Op_r <= ALU_Op;
Write_Data_r <= Write_Data;
if Break = '1' then
Set_Addr_To_r <= "00";
else
Set_Addr_To_r <= Set_Addr_To;
end if;
if Inc_S = '1' then
S <= S + 1;
end if;
if Dec_S = '1' and RstCycle = '0' then
S <= S - 1;
end if;
if LDS = '1' then
S(7 downto 0) <= unsigned(ALU_Q);
end if;
if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
PC <= PC + 1;
end if;
--
-- jump control logic
--
case Jump is
when "01" =>
PC <= PC + 1;
when "10" =>
PC <= unsigned(DI & DL);
when "11" =>
if PCAdder(8) = '1' then
if DL(7) = '0' then
PC(15 downto 8) <= PC(15 downto 8) + 1;
else
PC(15 downto 8) <= PC(15 downto 8) - 1;
end if;
end if;
PC(7 downto 0) <= PCAdder(7 downto 0);
when others => null;
end case;
end if;
end if;
end if;
end process;
PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
else "0" & PC(7 downto 0);
process (Clk)
begin
if Clk'event and Clk = '1' then
if (Enable = '1') then
if (really_rdy = '1') then
if MCycle = "000" then
if LDA = '1' then
ABC(7 downto 0) <= ALU_Q;
end if;
if LDX = '1' then
X(7 downto 0) <= ALU_Q;
end if;
if LDY = '1' then
Y(7 downto 0) <= ALU_Q;
end if;
if (LDA or LDX or LDY) = '1' then
P <= P_Out;
end if;
end if;
if SaveP = '1' then
P <= P_Out;
end if;
if LDP = '1' then
P <= ALU_Q;
end if;
if IR(4 downto 0) = "11000" then
case IR(7 downto 5) is
when "000" =>
P(Flag_C) <= '0';
when "001" =>
P(Flag_C) <= '1';
when "010" =>
P(Flag_I) <= '0';
when "011" =>
P(Flag_I) <= '1';
when "101" =>
P(Flag_V) <= '0';
when "110" =>
P(Flag_D) <= '0';
when "111" =>
P(Flag_D) <= '1';
when others =>
end case;
end if;
--if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
-- P(Flag_B) <= '1';
--end if;
--if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
-- P(Flag_I) <= '1';
-- P(Flag_B) <= B_o;
--end if;
-- B=1 always on the 6502
P(Flag_B) <= '1';
if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
if MCycle = "011" then
-- B=0 in *copy* of P pushed onto the stack
P(Flag_B) <= '0';
elsif MCycle = "100" then
P(Flag_I) <= '1';
end if;
end if;
if SO_n_o = '1' and SO_n = '0' then
P(Flag_V) <= '1';
end if;
if RstCycle = '1' and Mode_r /= "00" then
P(Flag_1) <= '1';
P(Flag_D) <= '0';
P(Flag_I) <= '1';
end if;
P(Flag_1) <= '1';
B_o <= P(Flag_B);
SO_n_o <= SO_n;
IRQ_n_o <= IRQ_n;
NMI_n_o <= NMI_n;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------
--
-- Buses
--
---------------------------------------------------------------------------
process (Res_n, Clk)
begin
if Res_n = '0' then
BusA_r <= (others => '0');
BusB <= (others => '0');
AD <= (others => '0');
BAL <= (others => '0');
BAH <= (others => '0');
DL <= (others => '0');
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
if (Rdy = '1') then
BusA_r <= BusA;
BusB <= DI;
case BAAdd is
when "01" =>
-- BA Inc
AD <= std_logic_vector(unsigned(AD) + 1);
BAL <= std_logic_vector(unsigned(BAL) + 1);
when "10" =>
-- BA Add
BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
when "11" =>
-- BA Adj
if BAL(8) = '1' then
BAH <= std_logic_vector(unsigned(BAH) + 1);
end if;
when others =>
end case;
-- ehenciak : modified to use Y register as well (bugfix)
if ADAdd = '1' then
if (AddY = '1') then
AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
else
AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
end if;
end if;
if IR = "00000000" then
BAL <= (others => '1');
BAH <= (others => '1');
if RstCycle = '1' then
BAL(2 downto 0) <= "100";
elsif NMICycle = '1' then
BAL(2 downto 0) <= "010";
else
BAL(2 downto 0) <= "110";
end if;
if Set_addr_To_r = "11" then
BAL(0) <= '1';
end if;
end if;
if LDDI = '1' then
DL <= DI;
end if;
if LDALU = '1' then
DL <= ALU_Q;
end if;
if LDAD = '1' then
AD <= DI;
end if;
if LDBAL = '1' then
BAL(7 downto 0) <= DI;
end if;
if LDBAH = '1' then
BAH <= DI;
end if;
end if;
end if;
end if;
end process;
Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
with Set_BusA_To select
BusA <= DI when "000",
ABC(7 downto 0) when "001",
X(7 downto 0) when "010",
Y(7 downto 0) when "011",
std_logic_vector(S(7 downto 0)) when "100",
P when "101",
(others => '-') when others;
with Set_Addr_To_r select
A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
DBR & "00000000" & AD when "10",
"00000000" & BAH & BAL(7 downto 0) when "11",
PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
with Write_Data_r select
DO <= DL when "000",
ABC(7 downto 0) when "001",
X(7 downto 0) when "010",
Y(7 downto 0) when "011",
std_logic_vector(S(7 downto 0)) when "100",
P when "101",
std_logic_vector(PC(7 downto 0)) when "110",
std_logic_vector(PC(15 downto 8)) when others;
-------------------------------------------------------------------------
--
-- Main state machine
--
-------------------------------------------------------------------------
process (Res_n, Clk)
begin
if Res_n = '0' then
MCycle <= "001";
RstCycle <= '1';
IRQCycle <= '0';
NMICycle <= '0';
NMIAct <= '0';
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
if (really_rdy = '1') then
if MCycle = LCycle or Break = '1' then
MCycle <= "000";
RstCycle <= '0';
IRQCycle <= '0';
NMICycle <= '0';
if NMIAct = '1' then
NMICycle <= '1';
elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
IRQCycle <= '1';
end if;
else
MCycle <= std_logic_vector(unsigned(MCycle) + 1);
end if;
if NMICycle = '1' then
NMIAct <= '0';
end if;
if NMI_n_o = '1' and NMI_n = '0' then
NMIAct <= '1';
end if;
end if;
end if;
end if;
end process;
end;

260
cores/c16/t65/T65_ALU.vhd Normal file
View File

@@ -0,0 +1,260 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 Bugfixes by ehenciak added
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- 6502 compatible microprocessor core
--
-- Version : 0245
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t65/
--
-- Limitations :
--
-- File history :
--
-- 0245 : First version
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T65_Pack.all;
entity T65_ALU is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
Op : in std_logic_vector(3 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
P_In : in std_logic_vector(7 downto 0);
P_Out : out std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0)
);
end T65_ALU;
architecture rtl of T65_ALU is
-- AddSub variables (temporary signals)
signal ADC_Z : std_logic;
signal ADC_C : std_logic;
signal ADC_V : std_logic;
signal ADC_N : std_logic;
signal ADC_Q : std_logic_vector(7 downto 0);
signal SBC_Z : std_logic;
signal SBC_C : std_logic;
signal SBC_V : std_logic;
signal SBC_N : std_logic;
signal SBC_Q : std_logic_vector(7 downto 0);
begin
process (P_In, BusA, BusB)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(6 downto 0);
variable C : std_logic;
begin
AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
-- pragma translate_off
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
-- pragma translate_on
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
ADC_Z <= '1';
else
ADC_Z <= '0';
end if;
if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
AL(6 downto 1) := AL(6 downto 1) + 6;
end if;
C := AL(6) or AL(5);
AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
ADC_N <= AH(4);
ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
-- pragma translate_off
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
-- pragma translate_on
if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
AH(6 downto 1) := AH(6 downto 1) + 6;
end if;
ADC_C <= AH(6) or AH(5);
ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
end process;
process (Op, P_In, BusA, BusB)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(5 downto 0);
variable C : std_logic;
begin
C := P_In(Flag_C) or not Op(0);
AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
-- pragma translate_off
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
-- pragma translate_on
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
SBC_Z <= '1';
else
SBC_Z <= '0';
end if;
SBC_C <= not AH(5);
SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
SBC_N <= AH(4);
if P_In(Flag_D) = '1' then
if AL(5) = '1' then
AL(5 downto 1) := AL(5 downto 1) - 6;
end if;
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
if AH(5) = '1' then
AH(5 downto 1) := AH(5 downto 1) - 6;
end if;
end if;
SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
end process;
process (Op, P_In, BusA, BusB,
ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
variable Q_t : std_logic_vector(7 downto 0);
begin
-- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
-- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
P_Out <= P_In;
Q_t := BusA;
case Op(3 downto 0) is
when "0000" =>
-- ORA
Q_t := BusA or BusB;
when "0001" =>
-- AND
Q_t := BusA and BusB;
when "0010" =>
-- EOR
Q_t := BusA xor BusB;
when "0011" =>
-- ADC
P_Out(Flag_V) <= ADC_V;
P_Out(Flag_C) <= ADC_C;
Q_t := ADC_Q;
when "0101" | "1101" =>
-- LDA
when "0110" =>
-- CMP
P_Out(Flag_C) <= SBC_C;
when "0111" =>
-- SBC
P_Out(Flag_V) <= SBC_V;
P_Out(Flag_C) <= SBC_C;
Q_t := SBC_Q;
when "1000" =>
-- ASL
Q_t := BusA(6 downto 0) & "0";
P_Out(Flag_C) <= BusA(7);
when "1001" =>
-- ROL
Q_t := BusA(6 downto 0) & P_In(Flag_C);
P_Out(Flag_C) <= BusA(7);
when "1010" =>
-- LSR
Q_t := "0" & BusA(7 downto 1);
P_Out(Flag_C) <= BusA(0);
when "1011" =>
-- ROR
Q_t := P_In(Flag_C) & BusA(7 downto 1);
P_Out(Flag_C) <= BusA(0);
when "1100" =>
-- BIT
P_Out(Flag_V) <= BusB(6);
when "1110" =>
-- DEC
Q_t := std_logic_vector(unsigned(BusA) - 1);
when "1111" =>
-- INC
Q_t := std_logic_vector(unsigned(BusA) + 1);
when others =>
end case;
case Op(3 downto 0) is
when "0011" =>
P_Out(Flag_N) <= ADC_N;
P_Out(Flag_Z) <= ADC_Z;
when "0110" | "0111" =>
P_Out(Flag_N) <= SBC_N;
P_Out(Flag_Z) <= SBC_Z;
when "0100" =>
when "1100" =>
P_Out(Flag_N) <= BusB(7);
if (BusA and BusB) = "00000000" then
P_Out(Flag_Z) <= '1';
else
P_Out(Flag_Z) <= '0';
end if;
when others =>
P_Out(Flag_N) <= Q_t(7);
if Q_t = "00000000" then
P_Out(Flag_Z) <= '1';
else
P_Out(Flag_Z) <= '0';
end if;
end case;
Q <= Q_t;
end process;
end;

1052
cores/c16/t65/T65_MCode.vhd Normal file

File diff suppressed because it is too large Load Diff

117
cores/c16/t65/T65_Pack.vhd Normal file
View File

@@ -0,0 +1,117 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 Bugfixes by ehenciak added
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- 65xx compatible microprocessor core
--
-- Version : 0246
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t65/
--
-- Limitations :
--
-- File history :
--
library IEEE;
use IEEE.std_logic_1164.all;
package T65_Pack is
constant Flag_C : integer := 0;
constant Flag_Z : integer := 1;
constant Flag_I : integer := 2;
constant Flag_D : integer := 3;
constant Flag_B : integer := 4;
constant Flag_1 : integer := 5;
constant Flag_V : integer := 6;
constant Flag_N : integer := 7;
component T65_MCode
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
IR : in std_logic_vector(7 downto 0);
MCycle : in std_logic_vector(2 downto 0);
P : in std_logic_vector(7 downto 0);
LCycle : out std_logic_vector(2 downto 0);
ALU_Op : out std_logic_vector(3 downto 0);
Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
BreakAtNA : out std_logic;
ADAdd : out std_logic;
AddY : out std_logic;
PCAdd : out std_logic;
Inc_S : out std_logic;
Dec_S : out std_logic;
LDA : out std_logic;
LDP : out std_logic;
LDX : out std_logic;
LDY : out std_logic;
LDS : out std_logic;
LDDI : out std_logic;
LDALU : out std_logic;
LDAD : out std_logic;
LDBAL : out std_logic;
LDBAH : out std_logic;
SaveP : out std_logic;
Write : out std_logic
);
end component;
component T65_ALU
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
Op : in std_logic_vector(3 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
P_In : in std_logic_vector(7 downto 0);
P_Out : out std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0)
);
end component;
end;

View File

@@ -1,23 +1,23 @@
//
// user_io.v - interface to MIST arm io controller
// user_io.v
//
// user_io for the MiST board
// http://code.google.com/p/mist-board/
//
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the 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
// 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/>.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// parameter STRLEN and the actual length of conf_str have to match
@@ -25,59 +25,62 @@
module user_io #(parameter STRLEN=0) (
input [(8*STRLEN)-1:0] conf_str,
input SPI_CLK,
input SPI_SS_IO,
output reg SPI_MISO,
input SPI_MOSI,
input clk_sys,
input SPI_CLK,
input SPI_SS_IO,
output reg SPI_MISO,
input SPI_MOSI,
output reg [7:0] joystick_0,
output reg [7:0] joystick_1,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoubler_disable,
output reg [7:0] status,
output reg [7:0] joystick_0,
output reg [7:0] joystick_1,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoubler_disable,
output reg [7:0] status,
// connection to sd card emulation
input [31:0] sd_lba,
input sd_rd,
input sd_wr,
output reg sd_ack,
input sd_conf,
input sd_sdhc,
output [7:0] sd_dout, // valid on rising edge of sd_dout_strobe
output reg sd_dout_strobe,
input [7:0] sd_din,
output reg sd_din_strobe,
output reg sd_change,
input [31:0] sd_lba,
input sd_rd,
input sd_wr,
output reg sd_ack,
output reg sd_ack_conf,
input sd_conf,
input sd_sdhc,
output reg [7:0] sd_dout, // valid on rising edge of sd_dout_strobe
output reg sd_dout_strobe,
input [7:0] sd_din,
output reg sd_din_strobe,
output reg [8:0] sd_buff_addr,
output reg img_mounted, //rising edge if a new image is mounted
// ps2 keyboard emulation
input ps2_clk, // 12-16khz provided by core
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
input ps2_clk, // 12-16khz provided by core
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
// serial com port
input [7:0] serial_data,
input serial_strobe
input [7:0] serial_data,
input serial_strobe
);
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [7:0] byte_cnt; // counts bytes
reg [5:0] joystick0;
reg [5:0] joystick1;
reg [7:0] but_sw;
reg [4:0] but_sw;
reg [2:0] stick_idx;
assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign sd_dout = { sbuf, SPI_MOSI};
// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
@@ -86,56 +89,9 @@ wire [7:0] core_type = 8'ha4;
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
// filter spi clock. the 8 bit gate delay is ~2.5ns in total
wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */;
wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
// drive MISO only when transmitting core id
always@(negedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
SPI_MISO <= 1'bZ;
end else begin
// first byte returned is always core type, further bytes are
// command dependent
if(byte_cnt == 0) begin
SPI_MISO <= core_type[~bit_cnt];
end else begin
// reading serial fifo
if(cmd == 8'h1b) begin
// send alternating flag byte and data
if(byte_cnt[0]) SPI_MISO <= serial_out_status[~bit_cnt];
else SPI_MISO <= serial_out_byte[~bit_cnt];
end
// reading config string
else if(cmd == 8'h14) begin
// returning a byte from string
if(byte_cnt < STRLEN + 1)
SPI_MISO <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
else
SPI_MISO <= 1'b0;
end
// reading sd card status
else if(cmd == 8'h16) begin
if(byte_cnt == 1)
SPI_MISO <= sd_cmd[~bit_cnt];
else if((byte_cnt >= 2) && (byte_cnt < 6))
SPI_MISO <= sd_lba[{5-byte_cnt, ~bit_cnt}];
else
SPI_MISO <= 1'b0;
end
// reading sd card write data
else if(cmd == 8'h18)
SPI_MISO <= sd_din[~bit_cnt];
else
SPI_MISO <= 1'b0;
end
end
end
//wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */;
//wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
wire spi_sck = SPI_CLK;
// ---------------- PS2 ---------------------
@@ -307,112 +263,206 @@ always@(negedge spi_sck or posedge status[0]) begin
end
end
// SPI receiver
always@(posedge spi_sck or posedge SPI_SS_IO) begin
// SPI bit and byte counters
always@(posedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
bit_cnt <= 3'd0;
byte_cnt <= 8'd0;
sd_ack <= 1'b0;
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
sd_change <= 1'b0;
bit_cnt <= 0;
byte_cnt <= 0;
end else begin
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
if(bit_cnt != 7)
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
bit_cnt <= bit_cnt + 3'd1;
if((bit_cnt == 7)&&(byte_cnt != 8'd255))
byte_cnt <= byte_cnt + 8'd1;
// finished reading command byte
if(bit_cnt == 7) begin
if(byte_cnt == 0) begin
cmd <= { sbuf, SPI_MOSI};
// fetch first byte when sectore FPGA->IO command has been seen
if({ sbuf, SPI_MOSI} == 8'h18)
sd_din_strobe <= 1'b1;
if(({ sbuf, SPI_MOSI} == 8'h17) || ({ sbuf, SPI_MOSI} == 8'h18))
sd_ack <= 1'b1;
end else begin
// buttons and switches
if(cmd == 8'h01)
but_sw <= { sbuf, SPI_MOSI };
bit_cnt <= bit_cnt + 1'd1;
end
end
if(cmd == 8'h02)
joystick_0 <= { sbuf, SPI_MOSI };
if(cmd == 8'h03)
joystick_1 <= { sbuf, SPI_MOSI };
if(cmd == 8'h04) begin
// store incoming ps2 mouse bytes
ps2_mouse_fifo[ps2_mouse_wptr] <= { sbuf, SPI_MOSI };
ps2_mouse_wptr <= ps2_mouse_wptr + 1;
end
// SPI transmitter FPGA -> IO
reg [7:0] spi_byte_out;
if(cmd == 8'h05) begin
// store incoming ps2 keyboard bytes
ps2_kbd_fifo[ps2_kbd_wptr] <= { sbuf, SPI_MOSI };
ps2_kbd_wptr <= ps2_kbd_wptr + 1;
end
if(cmd == 8'h15)
status <= { sbuf[6:0], SPI_MOSI };
// send sector IO -> FPGA
if(cmd == 8'h17) begin
// flag that download begins
sd_dout_strobe <= 1'b1;
end
// send sector FPGA -> IO
if(cmd == 8'h18)
sd_din_strobe <= 1'b1;
// send SD config IO -> FPGA
if(cmd == 8'h19) begin
// flag that download begins
// sd card knows data is config if sd_dout_strobe is asserted
// with sd_ack still being inactive (low)
sd_dout_strobe <= 1'b1;
end
// joystick analog
if(cmd == 8'h1a) begin
// first byte is joystick indes
if(byte_cnt == 1)
stick_idx <= { sbuf[1:0], SPI_MOSI };
else if(byte_cnt == 2) begin
// second byte is x axis
if(stick_idx == 0)
joystick_analog_0[15:8] <= { sbuf, SPI_MOSI };
else if(stick_idx == 1)
joystick_analog_1[15:8] <= { sbuf, SPI_MOSI };
end else if(byte_cnt == 3) begin
// third byte is y axis
if(stick_idx == 0)
joystick_analog_0[7:0] <= { sbuf, SPI_MOSI };
else if(stick_idx == 1)
joystick_analog_1[7:0] <= { sbuf, SPI_MOSI };
end
end
// set sd card status. The fact that this register is being
// set by the arm controller indicates a possible disk change
if(cmd == 8'h1c)
sd_change <= 1'b1;
always@(negedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
SPI_MISO <= 1'bZ;
end else begin
SPI_MISO <= spi_byte_out[~bit_cnt];
end
end
end
always@(posedge spi_sck or posedge SPI_SS_IO) begin
reg [31:0] sd_lba_r;
if(SPI_SS_IO == 1) begin
spi_byte_out <= core_type;
end else begin
// read the command byte to choose the response
if(bit_cnt == 7) begin
if(!byte_cnt) cmd <= {sbuf, SPI_MOSI};
spi_byte_out <= 0;
case({(!byte_cnt) ? {sbuf, SPI_MOSI} : cmd})
// reading config string
8'h14: if(byte_cnt < STRLEN) spi_byte_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8];
// reading sd card status
8'h16: if(byte_cnt == 0) begin
spi_byte_out <= sd_cmd;
sd_lba_r <= sd_lba;
end
else if(byte_cnt < 5) spi_byte_out <= sd_lba_r[(4-byte_cnt)<<3 +:8];
// reading sd card write data
8'h18: spi_byte_out <= sd_din;
8'h1b:
// send alternating flag byte and data
if(byte_cnt[0]) spi_byte_out <= serial_out_status;
else spi_byte_out <= serial_out_byte;
endcase
end
end
end
// SPI receiver IO -> FPGA
reg spi_receiver_strobe_r;
reg spi_transfer_end_r;
reg [7:0] spi_byte_in_r;
// Read at spi_sck clock domain, assemble bytes for transferring to clk_sys
always@(posedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
spi_receiver_strobe_r <= 0;
spi_transfer_end_r <= 1;
end else begin
spi_receiver_strobe_r <= 0;
spi_transfer_end_r <= 0;
if(bit_cnt != 7)
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
// finished reading a byte, prepare to transfer to clk_sys
if(bit_cnt == 7) begin
spi_byte_in_r <= { sbuf, SPI_MOSI};
spi_receiver_strobe_r <= 1;
end
end
end
// Process bytes from SPI at the clk_sys domain
always @(posedge clk_sys) begin
reg spi_receiver_strobe;
reg spi_transfer_end;
reg [7:0] spi_byte_in;
reg spi_receiver_strobeD;
reg spi_transfer_endD;
reg [7:0] spi_byte_inD;
reg [7:0] acmd;
reg [7:0] abyte_cnt; // counts bytes
//synchronize between SPI and sys clock domains
spi_receiver_strobeD <= spi_receiver_strobe_r;
spi_receiver_strobe <= spi_receiver_strobeD;
spi_transfer_endD <= spi_transfer_end_r;
spi_transfer_end <= spi_transfer_endD;
spi_byte_inD <= spi_byte_in_r;
spi_byte_in <= spi_byte_inD;
if(sd_dout_strobe) begin
sd_dout_strobe<= 0;
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
end
if(sd_din_strobe) begin
sd_din_strobe<= 0;
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
end
img_mounted <= 0;
if (~spi_transfer_endD & spi_transfer_end) begin
abyte_cnt <= 8'd0;
sd_ack <= 1'b0;
sd_ack_conf <= 1'b0;
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
sd_buff_addr<= 0;
end else if (~spi_receiver_strobeD & spi_receiver_strobe) begin
if(abyte_cnt != 8'd255)
abyte_cnt <= byte_cnt + 8'd1;
if(abyte_cnt == 0) begin
acmd <= spi_byte_in;
// fetch first byte when sectore FPGA->IO command has been seen
if(spi_byte_in == 8'h18)
sd_din_strobe <= 1'b1;
if((spi_byte_in == 8'h17) || (spi_byte_in == 8'h18))
sd_ack <= 1'b1;
end else begin
case(acmd)
// buttons and switches
8'h01: but_sw <= spi_byte_in;
8'h02: joystick_0 <= spi_byte_in;
8'h03: joystick_1 <= spi_byte_in;
8'h04: begin
// store incoming ps2 mouse bytes
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_byte_in;
ps2_mouse_wptr <= ps2_mouse_wptr + 1;
end
8'h05: begin
// store incoming ps2 keyboard bytes
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_byte_in;
ps2_kbd_wptr <= ps2_kbd_wptr + 1;
end
8'h15: status <= spi_byte_in;
// send sector IO -> FPGA
8'h17: begin
// flag that download begins
sd_dout_strobe <= 1'b1;
sd_dout <= spi_byte_in;
end
// send sector FPGA -> IO
8'h18: sd_din_strobe <= 1'b1;
// send SD config IO -> FPGA
8'h19: begin
// flag that download begins
sd_dout_strobe <= 1'b1;
sd_ack_conf <= 1'b1;
sd_dout <= spi_byte_in;
end
// joystick analog
8'h1a: begin
// first byte is joystick indes
if(abyte_cnt == 1)
stick_idx <= spi_byte_in[2:0];
else if(abyte_cnt == 2) begin
// second byte is x axis
if(stick_idx == 0)
joystick_analog_0[15:8] <= spi_byte_in;
else if(stick_idx == 1)
joystick_analog_1[15:8] <= spi_byte_in;
end else if(abyte_cnt == 3) begin
// third byte is y axis
if(stick_idx == 0)
joystick_analog_0[7:0] <= spi_byte_in;
else if(stick_idx == 1)
joystick_analog_1[7:0] <= spi_byte_in;
end
end
8'h1c: img_mounted <= 1;
endcase
end
end
end
endmodule