diff --git a/cores/c16/c1541/c1541_logic.vhd b/cores/c16/c1541/c1541_logic.vhd new file mode 100644 index 0000000..bb575b1 --- /dev/null +++ b/cores/c16/c1541/c1541_logic.vhd @@ -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; diff --git a/cores/c16/c1541/c1541_sd.vhd b/cores/c16/c1541/c1541_sd.vhd new file mode 100644 index 0000000..31eda55 --- /dev/null +++ b/cores/c16/c1541/c1541_sd.vhd @@ -0,0 +1,372 @@ +--------------------------------------------------------------------------------- +-- 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; + + 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"§or_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; + +end struct; diff --git a/cores/c16/c1541/c1541_sd.vhd.bak b/cores/c16/c1541/c1541_sd.vhd.bak new file mode 100644 index 0000000..3ff2824 --- /dev/null +++ b/cores/c16/c1541/c1541_sd.vhd.bak @@ -0,0 +1,311 @@ +--------------------------------------------------------------------------------- +-- 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); + + 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_miso : in std_logic; + sd_cs_n : buffer std_logic; + sd_mosi : buffer std_logic; + sd_sclk : buffer std_logic; + bus_available : in 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); + + +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 +); + +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; + + +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 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"§or_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; + +end struct; diff --git a/cores/c16/c1541/gcr_floppy.vhd b/cores/c16/c1541/gcr_floppy.vhd new file mode 100644 index 0000000..07621a3 --- /dev/null +++ b/cores/c16/c1541/gcr_floppy.vhd @@ -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"§or when "000000001", + "000"§or 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; diff --git a/cores/c16/m6522.vhd b/cores/c16/c1541/m6522.vhd similarity index 100% rename from cores/c16/m6522.vhd rename to cores/c16/c1541/m6522.vhd diff --git a/cores/c16/c1541/mist_sd_card.sv b/cores/c16/c1541/mist_sd_card.sv new file mode 100644 index 0000000..691e6dd --- /dev/null +++ b/cores/c16/c1541/mist_sd_card.sv @@ -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 . +// +// +///////////////////////////////////////////////////////////////////////// + +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 diff --git a/cores/c16/c1541/mist_sd_card.sv.bak b/cores/c16/c1541/mist_sd_card.sv.bak new file mode 100644 index 0000000..2b2f5b8 --- /dev/null +++ b/cores/c16/c1541/mist_sd_card.sv.bak @@ -0,0 +1,175 @@ +// +// 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 . +// +// +///////////////////////////////////////////////////////////////////////// + +module 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, + input [4:0] sector, + input [7:0] buff_addr, + output [7:0] buff_dout, + input [7:0] buff_din, + input buff_we, + output reg busy +); + +assign sd_lba = lba; + +trk_dpram buffer +( + .clock(clk), + + .address_a(sd_buff_base + base_fix + sd_buff_addr), + .data_a(sd_buff_dout), + .wren_a(sd_ack & sd_buff_wr), + .q_a(sd_buff_din), + + .address_b({sector, buff_addr}), + .data_b(buff_din), + .wren_b(buff_we), + .q_b(buff_dout) +); + +wire [9:0] start_sectors[41] = + '{ 0, 0, 21, 42, 63, 84,105,126,147,168,189,210,231,252,273,294,315,336,357,376,395, + 414,433,452,471,490,508,526,544,562,580,598,615,632,649,666,683,700,717,734,751}; + +reg [31:0] lba; +reg [12:0] base_fix; +reg [12:0] sd_buff_base; + +always @(posedge clk) begin + reg old_ack; + reg [5:0] cur_track = 0; + reg old_change, ready = 0; + reg saving = 0; + + old_change <= change; + if(~old_change & change) ready <= 1; + + old_ack <= sd_ack; + if(sd_ack) {sd_rd,sd_wr} <= 0; + + if(reset) begin + cur_track <= 'b111111; + busy <= 0; + sd_rd <= 0; + sd_wr <= 0; + saving<= 0; + end + else + if(busy) begin + if(old_ack && ~sd_ack) begin + if(sd_buff_base < 'h1800) begin + sd_buff_base <= sd_buff_base + 13'd512; + lba <= lba + 1'd1; + if(saving) sd_wr <= 1; + else sd_rd <= 1; + end + else + if(saving && (cur_track != track)) begin + saving <= 0; + cur_track <= track; + sd_buff_base <= 0; + base_fix <= start_sectors[track][0] ? 13'h1F00 : 13'h0000; + lba <= start_sectors[track][9:1]; + sd_rd <= 1; + end + else + begin + busy <= 0; + end + end + end + else + if(ready) begin + if(save_track && cur_track != 'b111111) begin + saving <= 1; + sd_buff_base <= 0; + lba <= start_sectors[cur_track][9:1]; + sd_wr <= 1; + busy <= 1; + end + else + if((cur_track != track) || (old_change && ~change)) begin + saving <= 0; + cur_track <= track; + sd_buff_base <= 0; + base_fix <= start_sectors[track][0] ? 13'h1F00 : 13'h0000; + lba <= start_sectors[track][9:1]; + sd_rd <= 1; + busy <= 1; + end + end +end + +endmodule + +module trk_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=13) +( + input clock, + + input [ADDRWIDTH-1:0] address_a, + input [DATAWIDTH-1:0] data_a, + input wren_a, + output reg [DATAWIDTH-1:0] q_a, + + input [ADDRWIDTH-1:0] address_b, + input [DATAWIDTH-1:0] data_b, + input wren_b, + output reg [DATAWIDTH-1:0] q_b +); + +logic [DATAWIDTH-1:0] ram[0:(1< '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; diff --git a/cores/c16/c1541/spram.vhd b/cores/c16/c1541/spram.vhd new file mode 100644 index 0000000..b010fb9 --- /dev/null +++ b/cores/c16/c1541/spram.vhd @@ -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; diff --git a/cores/c16/c1541/sprom.vhd b/cores/c16/c1541/sprom.vhd new file mode 100644 index 0000000..2b1ae58 --- /dev/null +++ b/cores/c16/c1541/sprom.vhd @@ -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; diff --git a/cores/c16/c1541_logic.vhd b/cores/c16/c1541_logic.vhd deleted file mode 100644 index 8cb1642..0000000 --- a/cores/c16/c1541_logic.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/c1541_sd.vhd b/cores/c16/c1541_sd.vhd deleted file mode 100644 index db0d4ae..0000000 --- a/cores/c16/c1541_sd.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/c16_mist.qsf b/cores/c16/c16_mist.qsf index ada9aef..b626ae6 100644 --- a/cores/c16/c16_mist.qsf +++ b/cores/c16/c16_mist.qsf @@ -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 \ No newline at end of file diff --git a/cores/c16/c16_mist.sdc b/cores/c16/c16_mist.sdc new file mode 100644 index 0000000..69c363c --- /dev/null +++ b/cores/c16/c16_mist.sdc @@ -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}] diff --git a/cores/c16/c16_mist.v b/cores/c16/c16_mist.v index ada848a..f0920b5 100644 --- a/cores/c16/c16_mist.v +++ b/cores/c16/c16_mist.v @@ -70,14 +70,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 +210,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 +252,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 ----------------------------- // --------------------------------------------------------------------------------- @@ -570,8 +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 = clk28_pal; 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 diff --git a/cores/c16/gcr_floppy.vhd b/cores/c16/gcr_floppy.vhd deleted file mode 100644 index 893b1ab..0000000 --- a/cores/c16/gcr_floppy.vhd +++ /dev/null @@ -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"§or when "000000001", - "000"§or 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; diff --git a/cores/c16/roms/325302-1_901229-03.hex b/cores/c16/roms/325302-1_901229-03.hex new file mode 100644 index 0000000..bd259f9 --- /dev/null +++ b/cores/c16/roms/325302-1_901229-03.hex @@ -0,0 +1,1025 @@ +:1000000097AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA63 +:10001000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA40 +:10002000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA30 +:10003000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA20 +:10004000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA10 +:10005000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00 +:10006000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0 +:10007000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0 +:10008000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0 +:10009000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0 +:1000A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0 +:1000B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0 +:1000C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA90 +:1000D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA80 +:1000E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA70 +:1000F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA60 +:1001000078A9F72D001C48A57FF005680900D003E9 +:100110006809088D001C586078A9080D001C8D0026 +:100120001C5860A9008D6C028D6D0260788A48A908 +:10013000508D6C02A200BDCAFE8D6D020D001C8D9B +:10014000001C68AA5860A9008DF902AD8E02857F57 +:1001500020BCE6A5841009290FC90FF0034CB4D7C1 +:1001600020B3C2B1A38D7502A20BBD89FECD75026D +:10017000F008CA10F5A9314CC8C18E2A02E00990D6 +:100180000320EEC1AE2A02BD95FE856FBDA1FE859E +:10019000706C6F00A9008DF902AD6C02D02AA0002E +:1001A000988480848184A320C7E62023C1A57F8D05 +:1001B0008E02AAA90095FF20BDC14CDAD4A028A9BF +:1001C000009900028810FA60A000848084814C4568 +:1001D000E6A2008E7A02A93A2068C2F00588888CCF +:1001E0007A024C68C3A000A200A93A4C68C220E57C +:1001F000C1D005A9344CC8C188888C7A028AD0F352 +:10020000A93D2068C28AF002A94009218D8B02E82D +:100210008E77028E7802AD8A02F00DA9800D8B02D6 +:100220008D8B02A9008D8A0298F0299D7A02AD7704 +:10023000028D7902A98D2068C2E88E7802CAAD8A43 +:1002400002F002A908EC7702F002090409034D8BC1 +:10025000028D8B02AD8B02AE2A023DA5FED001605D +:100260008D6C02A9304CC8C18D7502CC7402B02EC1 +:10027000B1A3C8CD7502F028C92AF004C93FD00344 +:10028000EE8A02C92CD0E4989D7B02AD8A02297FB8 +:10029000F007A98095E78D8A02E8E00490CDA000E0 +:1002A000AD74029D7B02AD8A02297FF004A980957E +:1002B000E79860A4A3F01488F010B90002C90DF00B +:1002C0000A88B90002C90DF002C8C88C7402C02A9D +:1002D000A0FF90088C2A02A9324CC8C1A0009885C2 +:1002E000A38D58028D4A028D960285D38D79028D99 +:1002F00077028D78028D8A028D6C02A2059D7902AB +:1003000095D795DC95E195E69D7F029D8402CAD044 +:10031000EC60AD78028D7702A9018D78028D7902AB +:10032000AC8E02A20086D3BD7A02203CC3A6D39D28 +:100330007A029895E2E8EC780290EA60AAA000A917 +:100340003ADD0102F00CDD0002D016E8982901A880 +:100350008A60BD0002E8E8C930F0F2C931F0EED0A1 +:10036000EB9809802981D0E7A9008D8B02AC7A0235 +:10037000B1A320BDC31011C8CC7402B006AC740286 +:1003800088D0EDCE8B02A9002901857F4C00C1A544 +:100390007F49012901857F60A000AD7702CD7802F9 +:1003A000F016CE7802AC7802B97A02A8B1A3A00404 +:1003B000D9BBFEF00388D0F8988D960260C930F062 +:1003C00006C931F0020980298160A900856F8D8DF1 +:1003D0000248AE780268056F48A901856FCA300FE0 +:1003E000B5E21004066F066F4A90EA066FD0E66821 +:1003F000AABD3FC44829038D8C02680A103EA5E2BD +:100400002901857FAD8C02F02B203DC6F012208F94 +:10041000C3A9008D8C02203DC6F01EA97420C8C15E +:10042000208FC3203DC608208FC328F00CA9008D63 +:100430008C02F005203DC6D0E24C00C12A4C00C41D +:1004400000804101010101818181814242424220BB +:10045000CAC3A9008D920220ACC5D019CE8C02105F +:100460000160A9018D8D02208FC32000C14C52C4B0 +:100470002017C6F01020D8C4AD8F02F00160AD5334 +:100480000230ED10F0AD8F02F0D2602004C6F01AF9 +:10049000D028A9018D8D02208FC32000C1A9008D15 +:1004A000920220ACC5D0138D8F02AD8F02D028CE22 +:1004B0008C0210DE602017C6F0F020D8C4AE5302C4 +:1004C0001007AD8F02F0EED00EAD9602F009B5E741 +:1004D0002907CD9602D0DE60A2FF8E5302E88E8AF5 +:1004E000022089C5F006602094C5D0FAA57F55E2A8 +:1004F0004A900B2940F0F0A902CD8C02F0E9BD7AB8 +:1005000002AA20A6C6A0034C1DC5BD0002D194F0CE +:100510000AC93FD0D2B194C9A0F0CCE8C8EC7602A9 +:10052000B009BD0002C92AF00CD0DFC013B006B17B +:1005300094C9A0D0B2AE79028E5302B5E729808D5E +:100540008A02AD940295DDA58195D8A000B194C82A +:10055000482940856F6829DF300209202927056F67 +:10056000856FA98035E7056F95E7B5E22980057F9E +:1005700095E2B1949D8002C8B1949D8502AD580268 +:10058000D007A015B1948D5802A9FF8D8F02AD78C8 +:10059000028D7902CE7902100160AE7902B5E730A2 +:1005A00005BD8002D0EEA9008D8F0260A0008C9165 +:1005B00002888C5302AD85FE8580A90185818D93CB +:1005C000022075D4AD9302D00160A9078D9502A9D0 +:1005D0000020F6D48D930220E8D4CE9502A000B17D +:1005E00094D018AD9102D02F203BDEA5818D9102D1 +:1005F000A594AE92028D9202F01D60A201EC9202CF +:10060000D02DF013AD85FE8580AD900285812075DB +:10061000D4AD940220C8D4A9FF8D5302AD95023009 +:1006200008A92020C6D14CD7C5204DD44CC4C5A59F +:10063000948D9402203BDEA5818D900260A568D048 +:1006400028A67F561C9022A9FF8D9802200ED0A0CC +:10065000FFC902F00AC903F006C90FF002A000A604 +:100660007F9895FFD0032042D0A67FB5FF60482039 +:10067000A6C62088C66838ED4B02AAF00A9008A9E1 +:10068000A09194C8CAD0FA60980AA8B99900859434 +:10069000B99A008595A000BD00029194C8F006E8C3 +:1006A000EC760290F260A9008D4B028A48BD0002F0 +:1006B000C92CF014C93DF010EE4B02E8A90FCD4B48 +:1006C000029005EC740290E58E760268AA60A5831C +:1006D00048A5824820DEC668858268858360A911A6 +:1006E000858320EBD020E8D4AD5302100AAD8D02F3 +:1006F000D00A2006C81860AD8D02F01FCE8D02D042 +:100700000DCE8D02208FC32006C8384C8FC3A900A0 +:100710008D73028D8D0220B7C73860A218A01DB15D +:10072000948D7302F002A21688B1948D7202E016C5 +:10073000F00AC90A9006CAC9649001CA20ACC7B1C0 +:1007400094480A1005A93C9DB20268290FA8B9C5B2 +:10075000FE9DB102CAB9C0FE9DB102CAB9BBFE9DE1 +:10076000B102CACAB005A92A9DB202A9A09DB102D0 +:10077000CAA012B1949DB102CA88C003B0F5A922E3 +:100780009DB102E8E020B00BBDB102C922F004C95E +:10079000A0D0F0A9229DB102E8E020B00AA97F3DD7 +:1007A000B1029DB10210F120B5C43860A01BA92090 +:1007B00099B00288D0FA602019F120DFF020ACC790 +:1007C000A9FF856FA67F8E7202A9008D7302A6F91C +:1007D000BDE0FE8595AD88FE8594A016B194C9A0B4 +:1007E000D00BA9312CB194C9A0D002A92099B30291 +:1007F0008810F2A9128DB102A9228DB2028DC30216 +:10080000A9208DC4026020ACC7A00BB917C899B14C +:10081000028810F74C4DEF424C4F434B5320465249 +:1008200045452E2098C32020C320CAC3A900858631 +:10083000209DC4303D20B7DD9033A000B194294005 +:10084000D02B20B6C8A013B194F00A8580C8B1940B +:100850008581207DC8AE5302A92035E7D00DBD802B +:10086000028580BD85028581207DC8E686208BC4F7 +:1008700010C3A5868580A901A0004CA3C1205FEF0D +:100880002075D42019F1B5A7C9FFF008ADF9020908 +:10089000408DF902A90020C8D42056D18580205669 +:1008A000D18581A580D00620F4EE4C27D2205FEFC1 +:1008B000204DD44C94C8A000989194205EDE4C99B1 +:1008C000D5A9314CC8C1A94C8D0006A9C78D010618 +:1008D000A9FA8D0206A90320D3D6A57F09E08503D6 +:1008E000A50330FCC9029007A903A2004C0AE660E8 +:1008F000A9E08D4F0220D1F02019F1A9FF95A7A9F9 +:100900000F8D560220E5C1D0034CC1C820F8C1208C +:1009100020C3AD8B022955D00FAE7A02BD0002C9AB +:100920002AD005A9304CC8C1AD8B0229D9D0F44CCE +:1009300052C9A9008D58028D8C028D80028D8102D2 +:10094000A5E32901857F09018D9102AD7B028D7A96 +:100950000260204FC4AD7802C9039045A5E2C5E30B +:10096000D03FA5DDC5DED039A5D8C5D9D03320CC40 +:10097000CAA9018D790220FAC92025D1F004C90243 +:10098000D005A96420C8C1A9128583AD3C028D3D64 +:1009900002A9FF8D3C02202ADAA20220B9C94C9498 +:1009A000C120A7C94C94C120E7CAA5E22901857FCF +:1009B0002086D420E4D6AE77028E790220FAC9A927 +:1009C00011858320EBD02025D1D0032053CAA9085C +:1009D00085F84CD8C9209BCF2035CAA98020A6DD38 +:1009E000F0F32025D1F003209BCFAE7902E8EC781C +:1009F0000290C6A91285834C02DBAE7902B5E229CA +:100A000001857FAD85FE8580B5D885812075D4AE02 +:100A10007902B5DD20C8D4AE7902B5E729078D4A41 +:100A200002A9008D580220A0D9A0012025D1F001F3 +:100A3000C8984CC8D4A9118583209BD38585A682EC +:100A4000B5F2290885F8D00A2025D1F005A9802023 +:100A500097DD6020D3D120CBE1A5D648A5D548A904 +:100A60001285832007D120D3D120CBE1209CE2A5A1 +:100A7000D68587A5D58586A900858885D485D7683C +:100A800085D56885D64C3BE32020C3A5E3290185A5 +:100A9000E3C5E2F002098085E2204FC420E7CAA541 +:100AA000E32901857FA5D985812057DE2099D5A529 +:100AB000DE18690320C8D42093DFA8AE7A02A910FB +:100AC000206EC6205EDE2099D54C94C1A5E829078A +:100AD0008D4A02AE7802CAEC7702900ABD8002D03D +:100AE000F5A9624CC8C16020CCCABD8002F005A93E +:100AF000634CC8C1CA10F360AD0102C92DD04CAD22 +:100B00000302856FAD04028570A000AD0202C952D8 +:100B1000F00E2058F2C957F037C945D02E6C6F003F +:100B2000B16F8585AD7402C906901AAE0502CAF090 +:100B3000148A18656FE66F8D4902A56F85A5A570AB +:100B400085A64C43D420EBD04C3AD4A9314CC8C133 +:100B5000B90602916FC8CC050290F560AC0102C0E5 +:100B600030D009A9EA856BA9FF856C602072CB4C57 +:100B700094C18898290F0AA8B16B8575C8B16B8597 +:100B8000766C7500AD8E02857FA58348203DC668D2 +:100B90008583AE7402CAD00DA90120E2D14CF1CBFD +:100BA000A9704CC8C1A001207CCCAE8502E005B084 +:100BB000EFA900856F857038266F2670CA10F9A5D9 +:100BC0006F2D4F02D0DAA5702D5002D0D3A56F0D36 +:100BD0004F028D4F02A5700D50028D5002A90020CA +:100BE000E2D1A682AD850295A7AAA57F95009D5B5F +:100BF00002A683BD2B0209409D2B02A482A9FF9966 +:100C00004402A98999F200B9A700993E020AAAA94B +:100C1000019599A90E99EC004C94C1A000A200A9DD +:100C20002D2068C2D00AA9314CC8C1A9304CC8C116 +:100C30008AD0F8A205B90002DD5DCCF005CA10F833 +:100C400030E48A09808D2A02206FCCAD2A020AAADC +:100C5000BD64CC8570BD63CC856F6C6F004146521E +:100C600057455003CDF5CC56CD73CDA3CDBDCDA00A +:100C700000A200A93A2068C2D002A003B90002C9AC +:100C800020F008C91DF004C92CD007C8CC7402900C +:100C9000EB6020A1CCEE7702AC7902E00490ECB0DE +:100CA0008AA900856F85708572A2FFB90002C940CC +:100CB000B018C9309014290F48A5708571A56F85AB +:100CC0007068856FC8CC740290E18C790218A90015 +:100CD000E8E003B00FB46F8830F67DF2CC90F818DE +:100CE000E672D0F348AE7702A5729D8002689D85BA +:100CF0000260010A6420F5CD205FEF4C94C1A90188 +:100D00008DF90220F5CDA5814820FAF1F00B68C5D8 +:100D100081D0192090EF4C94C168A9008581E680AC +:100D2000A580CDD7FEB00A20FAF1F0EEA9652045E6 +:100D3000E6A96520C8C120F2CD4C60D4202FD1A1F6 +:100D400099602036CDA90020C8D4203CCD9944021A +:100D5000A98999F200602042CD20ECD34C94C120A7 +:100D60006FCC2042CDB94402993E02A9FF994402BA +:100D70004C94C120F2CD20E8D4A888C902B002A0CA +:100D800001A90020C8D49820F1CF8A482064D468F3 +:100D9000AA20EED34C94C1206FCC20F2CD2064D495 +:100DA0004C94C12058F22036CDA900856FA6F9BD1C +:100DB000E0FE857020BACD4C94C16C6F0020D2CD7E +:100DC000A5F90AAAAD86029599202FD120EED34C21 +:100DD00094C1A6D3E6D3BD8502A88888C00C90052F +:100DE000A9704CC8C1858320EBD0B0F42093DF8577 +:100DF000F96020D2CDA6D3BD85022901857FBD87AC +:100E0000028581BD86028580205FD54C00C1202CE3 +:100E1000CE206ECEA59085D72071CEE6D7E6D7A599 +:100E20008B85D5A5900A18691085D66020D9CE8506 +:100E300092A682B5B58590B5BB8591D004A590F0FA +:100E40000BA59038E9018590B002C691B5C7856FB2 +:100E5000466F900320EDCE20E5CEA56FD0F2A5D44D +:100E600018658B858B9006E68CD002E68D60A9FE16 +:100E70002CA978856FA203B58F48B58A958F6895A0 +:100E80008ACAD0F320D9CEA200B590958FE8E004AD +:100E900090F7A9008592246F3009068F08468F28A5 +:100EA00020E6CE20EDCE20E5CE246F300320E2CE2A +:100EB000A58F18659085909006E691D002E692A5E0 +:100EC000920591D0C2A59038E56F900CE68BD006C4 +:100ED000E68CD002E68D859060A900858B858C8597 +:100EE0008D6020E5CE182690269126926018A2FDEE +:100EF000B58E7593958EE8D0F760A2008A95FAE8D2 +:100F0000E004D0F8A90695FA60A004A682B9FA0018 +:100F100096FAC582F0078830E1AA4C0DCF6020090F +:100F2000CF20B7DFD04620D3D1208ED2304820C288 +:100F3000DFA58048A58148A90120F6D48581A900B4 +:100F400020F6D48580F01F2025D1F00B20ABDDD01A +:100F500006208CCF4C5DCF208CCF2057DE6885815A +:100F60006885804C6FCF688581688580208CCF2014 +:100F700093DFAA4C99D5A9704CC8C12009CF20B7DE +:100F8000DFD008208ED230EE20C2DF60A682B5A767 +:100F9000498095A7B5AE498095AE60A212868320A0 +:100FA00007D12000C12025D19005A920209DDDA5D5 +:100FB00083C90FF023D008A584298FC90FB0192049 +:100FC00025D1B005A5854C9DD1D0034CABE0A585BE +:100FD00020F1CFA4824CEED3A904858220E8D4C9A5 +:100FE0002AF005A58520F1CFA5F8F00160EE5502A5 +:100FF00060482093DF100668A9614CC8C10AAA683E +:101000008199F6996020D1C12042D04C94C1200F23 +:10101000F1A8B6A7E0FFD01448208ED2AA1005A9E7 +:10102000702048E668A88A098099A7008A290F8558 +:10103000F9A2008681AE85FE868020D3D6A9B04C69 +:101040008CD520D1F02013D3200ED0A67FA9009DEF +:1010500051028A0AAAA5169512A51795132086D5BE +:10106000A5F90AAAA9029599A199A67F9D0101A9AE +:1010700000951C95FF203AEFA004A900AA18716DF5 +:101080009001E8C8C8C8C8C048F0F8C090D0EE4881 +:101090008AA67F9DFC02689DFA026020D0D620C3FC +:1010A000D02099D52037D185802037D18581602007 +:1010B0009BD0A580D00160201ECF20D0D620C3D0E9 +:1010C0004C1ECFA980D002A9908D4D022093DFAA9B +:1010D0002006D58A480AAAA90095992025D1C904D5 +:1010E000B006F6B5D002F6BB68AA60A583C9139016 +:1010F00002290FC90FD002A910AA38BD2B02300651 +:10110000290F8582AA1860A583C9139002290FAA06 +:10111000BD2B02A80A900A300A98290F8582AA18C6 +:101120006030F63860A682B5EC4A2907C904602011 +:1011300093DF0AAAA48260202FD1B94402F012A141 +:101140009948B599D94402D004A9FF959968F699B0 +:1011500060A199F699602037D1D0368585B94402CF +:10116000F008A98099F200A58560201ECFA9002073 +:10117000C8D42037D1C900F01985802037D18581A6 +:10118000201ECF20D3D120D0D620C3D0201ECFA563 +:1011900085602037D1A482994402A5856020F1CFD3 +:1011A000F0016020D3D1201EF1A90020C8D4A58071 +:1011B00020F1CFA58120F1CF20C7D0201ECF20D095 +:1011C000D6A9024CC8D4856F20E8D418656F9599CC +:1011D0008594602093DFAABD5B022901857F60387A +:1011E000B0011808856F2027D2207FD38582A6837F +:1011F00028900209809D2B02293FA8A9FF99A700EA +:1012000099AE0099CD00C66F301C208ED2100820F8 +:101210005AD2A9704CC8C199A700C66F3008208E59 +:10122000D230EC99AE0060A583C90FD00160A683CF +:10123000BD2B02C9FFF022293F8582A9FF9D2B0209 +:10124000A682A90095F2205AD2A682A901CA30032B +:101250000AD0FA0D56028D560260A682B5A7C9FFC4 +:10126000F00948A9FF95A76820F3D2A682B5AEC9B8 +:10127000FFF00948A9FF95AE6820F3D2A682B5CD4C +:10128000C9FFF00948A9FF95CD6820F3D2609848BE +:10129000A00120BAD2100C8820BAD210062039D36F +:1012A000AA3013B50030FCA57F95009D5B028A0A29 +:1012B000A8A90299990068A88A60A207B94F023DBF +:1012C000E9EFF004CA10F560B94F025DE9EF994FFC +:1012D000028A883003186908AA60A682B5A7300977 +:1012E0008A186907AAB5A710F0C9FFF0EC48A9FF52 +:1012F00095A768290FA8C8A2106E50026E4F0288E9 +:10130000D00118CA10F360A90E85832027D2C683A6 +:10131000D0F960A90E8583A683BD2B02C9FFF01406 +:10132000293F85822093DFAABD5B022901C57FD0BA +:10133000032027D2C68310DF60A56F48A000B6FA4D +:10134000B5A71004C9FFD0168A186907AAB5A71057 +:1013500004C9FFD009C8C00590E4A2FFD01C866F65 +:10136000293FAAB50030FCC9029008A66FE007909B +:10137000D7B0E2A46FA9FF99A70068856F8A60A023 +:1013800000A9012C5602D009C80AD0F7A9704CC890 +:10139000C149FF2D56028D5602986020EBD02000E7 +:1013A000C120AAD3A682BD3E0260A6822025D1D04C +:1013B000034C20E1A583C90FF05AB5F22908D013D8 +:1013C0002025D1C907D007A98995F24CDED3A90001 +:1013D00095F260A583F0322025D1C9049022202FF8 +:1013E000D1B599D94402D004A9009599F699A1994B +:1013F000993E02B599D94402D005A98199F20060BD +:101400002056D1A6829D3E0260AD5402F0F22067C4 +:10141000ED4C03D420E8D4C9D4D018A595C902D086 +:1014200012A90D85852023C1A90020C1E6C6A5A962 +:1014300080D0122037D18585D009A9D420C8D4A95D +:1014400002959AA98885F7A5858D4302602093DFD0 +:101450000AAAA9009599A199F005D6994C56D16090 +:10146000A980D002A990057F8D4D02A5F920D3D681 +:10147000A6F94C93D5A9018D4A02A911858320466E +:10148000DCA9024CC8D4A91285834CDADC203BDEEF +:10149000A901856FA56948A9038569202DF1688593 +:1014A00069A90020C8D4A58020F1CFA58120F1CF63 +:1014B00020C7D02099D5A90020C8D420F1CFD0FBD7 +:1014C00020F1CFA9FF4CF1CF856F2093DF0AAAB599 +:1014D0009A8595A56F9599859460A9118583202794 +:1014E000D2A91285834C27D22093DF0AAAB59A8508 +:1014F00095B59985946085712093DFAABDE0FE853E +:1015000072A000B17160BD5B0229010D4D024886D9 +:10151000F98A0AAAB5078D4D02B506F02DCDD7FE82 +:10152000B028AA684829F0C990D04F68484AB00549 +:10153000AD01019003AD0201F005CDD5FED0338A97 +:10154000204BF2CD4D02F002B0302052D5A9664CAE +:1015500045E6A5F90AAAB5068580B507858160A587 +:1015600080F0EACDD7FEB0E5204BF2C581F0DE90E9 +:10157000DC602052D5A9734C45E6A6F9688D4D0272 +:1015800095009D5B0260A980D002A990057FA6F915 +:101590008D4D02AD4D02200ED520A6D5B0FB48A939 +:1015A000008D98026860B500301AC9029014C9080D +:1015B000F008C90BF004C90FD00C2C980230034C72 +:1015C0003FD6186038609848A57F48BD5B02290166 +:1015D000857FA8B9CAFE8D6D0220A6D6C902B003C8 +:1015E0004C6DD6BD5B0229F048C990D007A57F0994 +:1015F000B89D5B02246A7039A9008D99028D9A0208 +:10160000AC9902AD9A0238F9DBFE8D9A02B9DBFE85 +:101610002076D6EE990220A6D6C9029008AC99028F +:10162000B9DBFED0DBAD9A022076D6B500C90290B8 +:101630002B246A100F68C990D005057F9D5B02B509 +:1016400000200AE6682C9802302348A9C0057F953F +:1016500000B50030FC20A6D6C902B0D968C990D028 +:101660000C057F9D5B0220A6D6C902B0D268857F9B +:1016700068A8B5001860C900F018300CA0012093CC +:10168000D638E901D0F6F00AA0FF2093D6186901F8 +:10169000D0F6604898A47F99FE02D9FE02F0FBA91B +:1016A0000099FE026860A56A293FA8AD6D024D0051 +:1016B0001C8D001CBD5B029500B50030FCC902907A +:1016C0000388D0E748AD6D020D001C8D001C6860DA +:1016D0002093DF0AA8A580990600A581990700A597 +:1016E0007F0AAA60A58348A58248A58148A58048AD +:1016F000A9118583203BDEAD4A0248A5E229018578 +:101700007FA6F95D5B024A900CA2018E920220AC8A +:10171000C5F01DD028AD9102F00CC581F01F858168 +:101720002060D44C3DD7A9018D92022017C6D00D60 +:10173000208DD4A5818D9102A9028D9202AD9202D5 +:1017400020C8D4688D4A02C904D002098020F1CF94 +:10175000688D800220F1CF688D850220F1CF209323 +:10176000DFA8AD7A02AAA910206EC6A010A9009128 +:1017700094C8C01B90F9AD4A02C904D013A010ADA3 +:1017800059029194C8AD5A029194C8AD58029194EF +:101790002064D4688582AA688583AD910285D89D2E +:1017A0006002AD920285DD9D6602AD4A0285E7A525 +:1017B0007F85E260A5838D4C0220B3C28E2A02AEE3 +:1017C0000002AD4C02D02CE02AD028A57EF04D8539 +:1017D00080AD6E02857F85E2A90285E7AD6F028547 +:1017E000812000C12046DCA904057FA68299EC0077 +:1017F0004C94C1E024D01EAD4C02D0034C55DA20ED +:10180000D1C1AD85FE8580A90085812046DCA57FFC +:1018100009024CEBD7E023D0124C84CBA9028D9661 +:1018200002A900857F8D8E022042D020E5C1D00420 +:10183000A200F00C8AF005A9304CC8C188F00188DC +:101840008C7A02A98D2068C2E88E78022012C3200B +:10185000CAC3209DC4A2008E58028E97028E4A02EF +:10186000E8EC7702B0102009DAE8EC7702B007C0A4 +:1018700004F03E2009DAAE4C028683E002B0128EFC +:101880009702A9408DF902AD4A02D01BA9028D4AE8 +:1018900002AD4A02D011A5E729078D4A02AD8002A8 +:1018A000D005A9018D4A02AD9702C901F0184C403C +:1018B000D9BC7A02B900028D5802AD8002D0B7A916 +:1018C000018D9702D0B0A5E72980AAD014A92024C1 +:1018D000E7F00620B6C84CE3D9AD8002D0034CE354 +:1018E000D9AD0002C940F00D8AD005A9634CC8C12A +:1018F000A9334CC8C1A5E72907CD4A02D067C9045E +:10190000F06320DADCA5828D7002A911858320EBBB +:10191000D0AD940220C8D4A000B19409209194A025 +:101920001AA5809194C8A5819194AE7002A5D89D06 +:101930006002A5DD9D6602203BDE2064D44CEFD919 +:10194000AD8002D005A9624CC8C1AD9702C903F0B1 +:101950000BA92024E7F005A9604CC8C1A5E7290719 +:10196000CD4A02F005A9644CC8C1A0008C7902AE32 +:101970009702E002D01AC904F0EBB194294F919478 +:10198000A58348A9118583203BDE2064D468858324 +:1019900020A0D9AD9702C902D055202ADA4C94C1B3 +:1019A000A013B1948D5902C8B1948D5A02C8B19454 +:1019B000AE58028D58028AF00ACD5802F005A9509F +:1019C00020C8C1AE7902BD80028580BD85028581B7 +:1019D0002046DCA482AE7902B5D8996002B5DD99C3 +:1019E000660260A5E22901857F20DADC20E4D6A525 +:1019F00083C902B011203EDEA580857EA57F8D6E55 +:101A000002A5818D6F024C99C1BC7A02B90002A077 +:101A100004883008D9B2FED0F88C9702A00588302F +:101A200008D9B6FED0F88C4A02602039CAA98020B5 +:101A3000A6DDF0F62095DEA681E88AD00520A3D1A8 +:101A4000A90220C8D4A682A90195F2A9800582A680 +:101A5000839D2B0260A90C8D2A02A900AE7402CAD4 +:101A6000F00BCAD021AD010220BDC3301985E2EED2 +:101A70007702EE7802EE7A02A98085E7A92A8D0026 +:101A8000028D0102D01820E5C1D00520DCC2A003E0 +:101A900088888C7A022000C22098C32020C320CAE4 +:101AA000C320B7C7209DC4209EEC2037D1A6829DBD +:101AB0003E02A57F8D8E02090495ECA90085A360E6 +:101AC000A9008DF902A583D00BA9008D540220270F +:101AD000D24CDAD4C90FF0142002DBA583C90290DE +:101AE000F0AD6C02D0034C94C14CADC1A90E8583FE +:101AF0002002DBC68310F9AD6C02D0034C94C14CBC +:101B0000ADC1A683BD2B02C9FFD00160290F85821C +:101B10002025D1C907F00FC904F0112007D1B00961 +:101B20002062DB20A5DB20F4EE4C27D220F1DD2063 +:101B30001ECF20CBE1A6D58673E673A900857085FC +:101B400071A5D638E90E85722051DFA682A5709561 +:101B5000B5A57195BBA94020A6DDF00320A5DB4CFF +:101B600027D2A682B5B515BBD00C20E8D4C902D0C7 +:101B700005A90D20F1CF20E8D4C902D00F201ECF37 +:101B8000A682B5B5D002D6BBD6B5A90038E90148C2 +:101B9000A90020C8D420F1CF6820F1CF20C7D020E1 +:101BA00099D54C1ECFA6828E7002A58348BD6002D7 +:101BB0008581BD66028D9402B5EC2901857FAD85D6 +:101BC000FE85802093DF4885F92060D4A000BDE029 +:101BD000FE8587AD94028586B1862920F0432025B5 +:101BE000D1C904F044B186298F9186C8B186858019 +:101BF0008471A01BB1864888B186D00A858068852B +:101C000081A9672045E648A9009186C8918668A405 +:101C1000719186C8B1868581689186207DC84C29DE +:101C2000DCB186290F09809186AE7002A01CB5B583 +:101C30009186C8B5BB918668AAA990057F2090D5EA +:101C40006885834C07D1A90120E2D120B6DCAD4ADA +:101C500002480A057F95EC209BD0A682A580D0057E +:101C6000A5819D440268C904D03FA483B92B020911 +:101C700040992B02AD580295C7208ED210034C0F0D +:101C8000D2A68295CDAC59028480AC5A02848120C0 +:101C9000D3D62073DE2099D5A682A90295C1A900CA +:101CA00020C8D42053E14C3EDE2056D1A6829D3E72 +:101CB00002A98895F260A682B5A70AA8A9029999F7 +:101CC00000B5AE098095AE0AA8A902999900A900AD +:101CD00095B595BBA9009D44026020A9F1A90120FA +:101CE000DFD120D0D620B6DCA682AD4A02480A0554 +:101CF0007F95EC68C904F005A90195F260A483B949 +:101D00002B02293F0940992B02AD580295C7208E1E +:101D1000D210034C0FD2A68295CD20C1DE201EF139 +:101D2000A5808D5902A5818D5A02A682B5CD20D3FA +:101D3000D6A90020E9DEA900208DDDA911208DDDC6 +:101D4000A900208DDDAD5802208DDDA580208DDD20 +:101D5000A581208DDDA91020E9DE203EDEA58020B2 +:101D60008DDDA581208DDD206CDE2099D5A9022096 +:101D7000C8D4A68238A900F5C795C120E2E220198F +:101D8000DE205EDE2099D520F4EE4C98DC48A68259 +:101D9000B5CD4CFDCF9006A68215ECD006A68249A3 +:101DA000FF35EC95EC60A68235EC602093DFAABD90 +:101DB0005B0229F0C99060A2008671BD2B02C9FFA9 +:101DC000D008A671E8E01090F0608671293FA8B9AC +:101DD000EC0029018570AE5302B5E22901C570D02F +:101DE000E1B96002D5D8D0DAB96602D5DDD0D31812 +:101DF00060209EDF5006205EDE2099D560202BDE1D +:101E0000A5809194C8A58191944C05E1202BDEB169 +:101E1000948580C8B194858160202BDEA9009194BF +:101E2000C8A682B5C1AACA8A9194602093DF0AAA83 +:101E3000B59A8595A9008594A0006020EBD02093E9 +:101E4000DF85F90AA8B906008580B9070085816099 +:101E5000A9908D4D02D028A9808D4D02D021A99046 +:101E60008D4D02D026A9808D4D02D01FA9908D4D99 +:101E700002D002A9808D4D02A682B5CDAA101320F2 +:101E8000D0D62093DFAAA57F9D5B022015E1209389 +:101E9000DFAA4C06D5A90020C8D42037D1858020E0 +:101EA00037D185816048A900856F8571B9E0FE85CD +:101EB00070BDE0FE857268A888B16F91718810F9D5 +:101EC00060A8B9E0FE8570A900856FA8916FC8D0A1 +:101ED000FB60A90020DCDEA002B194608594A6829C +:101EE000B5CDAABDE0FE8595604820DCDE488A0AB3 +:101EF000AA68959A689599602066DF300E5013A6FF +:101F000082B5CD201BDF2066DF100720CBE12CCE71 +:101F1000FE60A5D620E9DE2CCDFE6085F9A980D033 +:101F20000485F9A99048B5EC2901857F68057F8D66 +:101F30004D02B1948580C8B1948581A5F920D3D68E +:101F4000A6F94C93D5A682B5CD4CEBD4A978205CEC +:101F5000DFCA10F8A5724A205CDFA573186570858A +:101F6000709002E6716020D2DEC5D5D00EA4D6B145 +:101F700094F0042CCDFE602CCFFE60A5D5C906B030 +:101F80000A0AA8A9048594B194D0042CD0FE602C30 +:101F9000CEFE60A682B5A71002B5AE29BF60A682AC +:101FA0008E5702B5A710098A1869078D5702B5AE7A +:101FB0008570291F247060A682B5A73002B5AEC90E +:101FC000FF60A6820980B4A7100395A76095AE6054 +:101FD000A920209DDDA98020A6DDD041A682F6B5EE +:101FE000D002F6BBA682B5C1F02E20E8D4A682D5D9 +:101FF000C19003203CE0A682B5C120C8D4A1998538 +:1020000085A920209DDD2004E3489028A90020F622 +:10201000D4D02168C902F012A9802097DD202FD1E9 +:10202000B599994402A90D8585602035E0A682A95D +:102030000095C16068A68295C14C6EE120D3D12085 +:1020400095DE209EDF5016205EDE201ECFA90220E6 +:10205000C8D420ABDDD0242057DE4C99D5201ECF2C +:1020600020ABDDD0062057DE2099D52095DEA58057 +:10207000F009201ECF2057DE201ECF602005E12072 +:1020800093DF0AAAA5858199B499C8D009A482B919 +:10209000C100F00AA00298A482D9C100D005A920ED +:1020A0004C97DDF699D003203CE060A9A020A6DD86 +:1020B000D027A585207CE0A5F8F00D60A92020A6FA +:1020C000DDF005A9518D6C0220F3E02053E1AD6CE9 +:1020D00002F0034CC8C14CBCE62980D005A5F8F03D +:1020E000DB60A58548201CE3688585A980209DDDEF +:1020F0004CB2E0A92020A6DDD00AA9008585207C6D +:10210000E04CF3E060A9402097DD209EDF0940AE5F +:10211000570295A760209EDF29BFAE570295A760A2 +:10212000A98020A6DDD037202FD1B599D94402F05F +:1021300022F699D006203CE0202FD1A199993E02A9 +:10214000A98999F200B599D94402F00160A9819951 +:10215000F2006020D0DF202FD1A5854C3DE1A68282 +:10216000A90D9D3E02A98195F2A95020C8C1A68261 +:10217000B5C18587C687C902D004A9FF8587B5C7C1 +:10218000858820E8D4A682C5879019F017201ECF35 +:1021900020B2E19008A6829D44024C1ECF201ECFA3 +:1021A000A9FF858720B2E1B00320E8D4A6829D4430 +:1021B0000260202BDEA487B194D00D88C002900469 +:1021C000C688D0F3C688186098386020D2DE85D5DE +:1021D000A9048594A00AD00488883026B194F0F828 +:1021E000984AC5D5F00985D5A682B5CD201BDFA0BC +:1021F000008494B194D00BC8B194A88884D6984C2C +:10220000E9DEA9672045E620B3C2AD01028583203F +:10221000EBD09005A97020C8C1A9A0209DDD202584 +:10222000D1F005A96420C8C1B5EC2901857FAD02B4 +:102230000295B5AD030295BBA682A98995F2AD04BE +:1022400002F01038E901F00BD5C79007A9518D6C49 +:1022500002A90085D4200ECE20F8DE5008A98020E7 +:1022600097DD4C5EE12075E2A98020A6DDF0034CED +:102270005EE14C94C1209CE2A5D720C8D4A682B5CB +:10228000C738E5D4B0034C02E21865D79003690162 +:10229000382009E04C38E1A95120C8C1A5948589AE +:1022A000A595858A20D0E2D0016020F1DD200CDEEA +:1022B000A580F00E20D3E2D006201ECF4CDAD2202B +:1022C000DAD2A000B1898580C8B18985814CAFD0B0 +:1022D000203EDEA000B189C580F00160C8B189C58B +:1022E0008160202BDEA002A9009194C8D0FB2004BD +:1022F000E395C1A8A9FF91942004E390F4D004A928 +:102300000095C160A682B5C138F00D1875C7900B55 +:10231000D006A9022CCCFE606901386020D3D12000 +:10232000CBE1209CE2207BCFA5D68587A5D58586ED +:10233000A9008588A90085D4200ECE204DEFA48267 +:10234000B6C7CA8A1865D7900CE6D6E6D6D006E698 +:10235000D5A91085D6A58718690220E9DEA5D5C9BB +:10236000069005A95220C8C1A5D638E587B003E973 +:102370000F188572A5D5E5868573A20086708671D3 +:10238000AA2051DFA571D007A670CAD002E688CD79 +:1023900073029009D0CDAD7202C57090C6A901201C +:1023A000F6D4186901A68295C1201EF120FDDDA595 +:1023B00088D015205EDE201ECF20D0D6201EF12032 +:1023C000FDDD20E2E24CD4E3201ECF20D0D620E277 +:1023D000E22019DE205EDE200CDEA58048A58148C3 +:1023E000203EDEA58148A580482045DFAAD00A20EE +:1023F0004EE4A91020E9DEE68668208DDD68208D98 +:10240000DD688581688580F00FA586C5D5D0A720B9 +:1024100045DFC5D690A0F0B02045DF48A90020DCFC +:10242000DEA900A89194C86838E9019194206CDE77 +:102430002099D520F4EE200ECE201ECF20F8DE709D +:10244000034C75E2A9802097DDA95020C8C1201E49 +:10245000F1201ECF20F1DD2093DF4820C1DEA682CF +:10246000B5CDA868AAA91020A5DEA90020DCDEA0B1 +:1024700002B19448A90020C8D46818690191940A4F +:1024800069048589A838E902858AA58085879194A1 +:10249000C8A58185889194A000989194C8A91191AC +:1024A00094A91020C8D42050DE2099D5A682B5CD9D +:1024B00048209EDFA68295CD68AE570295A7A90059 +:1024C00020C8D4A000A5809194C8A58191944CDE29 +:1024D000E42093DFA682201BDFA90020C8D4C68A8F +:1024E000C68AA489A5879194C8A5889194205EDEA8 +:1024F0002099D5A48AC003B0D84C1ECF00A04FCBE2 +:10250000202122232427D245414489528320544F3D +:102510004F204C415247C5508B06205052455345E1 +:102520004ED451CF564552464C4F5720494E8B25DD +:10253000288A89268A2050524F54454354204FCE32 +:102540002988204944853031323334D3594E54419F +:102550005889608A03846383204558495354D3645F +:102560008320545950458565CE4F20424C4F43CB74 +:102570006667C94C4C4547414C20545241434B205F +:102580004F5220534543544FD261830684396283AE +:102590000687018353205343524154434845C47036 +:1025A000CE4F204348414E4E45CC71C449528972AA +:1025B000882046554CCC73C3424D20444F5320567F +:1025C000322E3620313534B174C452495645062076 +:1025D00052454144D909C552524FD20AD7524954A3 +:1025E000C503C6494CC504CF5045CE05CD49534D12 +:1025F000415443C806CE4FD407C64F554EC408C4F5 +:102600004953CB0BD245434F52C44886F98A0AAA94 +:10261000B5068580B507858168290FF008C90FD0F8 +:1026200006A974D008A9060920AACACA8A48AD2AF0 +:1026300002C900D00FA9FF8D2A026820C7E62042F8 +:10264000D04C48E66820C7E620BDC1A9008DF9023C +:10265000202CC120DAD4A90085A3A2459AA58429FB +:102660000F8583C90FF03178A579D01CA57AD010D9 +:10267000A683BD2B02C9FFF01F290F85824C8EE671 +:1026800020EBD0204EEAD0062007D1204EEA2025AC +:10269000D1C904B0032027D24CE7EBAAA900F8E087 +:1026A00000F007186901CA4C9FE6D8AA4A4A4A4A6C +:1026B00020B4E68A290F093091A5C8602023C1A95A +:1026C00000A00084808481A000A2D586A5A20286F5 +:1026D000A620ABE6A92C91A5C8ADD5028D43028AF0 +:1026E0002006E7A92C91A5C8A580209BE6A92C91DE +:1026F000A5C8A581209BE688981869D58D4902E672 +:10270000A5A98885F760AAA58648A58748A9FC855C +:1027100086A9E485878AA200C186F021482075E752 +:1027200090052075E790FBA587C9E69008D00AA917 +:102730000AC5869004684C18E7684C4DE72067E7A7 +:1027400090FB2054E72067E790F82054E7688587DE +:1027500068858660C920B00BAAA92091A5C88A20E7 +:1027600006E76091A5C860E686D002E687A1860AE2 +:10277000A186297F60206DE7E686D002E68760604B +:10278000AD0018AA2904F0F78A2901F0F258AD002B +:10279000182905D0F9EE7802EE7402A92A8D0002FC +:1027A0004CA8E7A98D2068C22058F2AD780248A94C +:1027B000018D7802A9FF8586204FC4AD8002D00527 +:1027C000A93920C8C1688D7802AD80028580AD85A9 +:1027D000028581A9032077D4A90085872039E8855F +:1027E00088204BE82039E88589204BE8A586F00A47 +:1027F000A58848A58948A90085862039E8858A20CA +:102800004BE82039E8A0009188204BE8A58818699A +:102810000185889002E689C68AD0E72035CAA58559 +:10282000C587F008203EDEA9502045E6A5F8D0A8CF +:102830006885896885886C88002035CAA5F8D00825 +:10284000203EDEA9512045E6A58560186587690010 +:10285000858760AD0118A901857C6078A900857C19 +:102860008579857AA2459AA98085F8857D20B7E982 +:1028700020A5E9AD001809108D0018AD00181057FB +:102880002904D0F720C9E9C93FD006A9008579F00D +:1028900071C95FD006A900857AF067C578D00AA90A +:1028A00001857AA9008579F029C577D00AA9018523 +:1028B00079A900857AF01BAA2960C960D03F8A8572 +:1028C00084290F8583A58429F0C9E0D0355820C01C +:1028D000DA782C001830ADA900857DAD001829EFFD +:1028E0008D0018A579F006202EEA4CE7EBA57AF0CA +:1028F00009209CE920AEE92009E94C4EEAA9108D97 +:1029000000182C001810D030F97820EBD0B006A6B3 +:1029100082B5F23001602059EA20C0E9290108207F +:10292000B7E928F0122059EA20C0E92901D0F6A61B +:1029300082B5F22908D0142059EA20C0E92901D033 +:10294000F62059EA20C0E92901F0F620AEE9205925 +:10295000EA20C0E92901D0F3A908859820C0E92917 +:1029600001D036A682BD3E026A9D3E02B00520A57A +:10297000E9D003209CE920B7E9A523D00320F3FE8A +:1029800020FBFEC698D0D52059EA20C0E92901F0E5 +:10299000F65820AAD3784C0FE94C4EEAAD0018291E +:1029A000FD8D001860AD001809028D001860AD00A3 +:1029B0001809088D001860AD001829F78D001860FF +:1029C000AD0018CD0018D0F860A90885982059EA04 +:1029D00020C0E92904D0F6209CE9A9018D05182022 +:1029E00059EAAD0D182940D00920C0E92904F0EFBB +:1029F000D01920A5E9A20ACAD0FD209CE92059EAF5 +:102A000020C0E92904F0F6A90085F8AD00184901B5 +:102A10004A2902D0F6EAEAEA66852059EA20C0E9A6 +:102A20002904F0F6C698D0E320A5E9A585607820B2 +:102A300007D1B005B5F26AB00BA58429F0C9F0F052 +:102A4000034C4EEA20C9E95820B7CF4C2EEAA90022 +:102A50008D00184CE7EB4C5BE8A57DF006AD001847 +:102A6000100960AD001810FA4C5BE84CD7E8A200E2 +:102A70002CA66F9ABAA9080D001C4CEAFE9818699A +:102A800001D0FC88D0F8AD001C29F78D001C9818E7 +:102A90006901D0FC88D0F8CA10DBE0FCD0F0F0D49B +:102AA00078D8A2FF8E0318E8A000A2008A9500E85B +:102AB000D0FA8AD500D0B7F600C8D0FBD500D0AE8A +:102AC0009400B500D0A8E8D0E9E66F8676A9008525 +:102AD00075A8A22018C6767175C8D0FBCAD0F66951 +:102AE00000AAC576D039E0C0D0DFA9018576E66FAF +:102AF000A207981865769175C8D0F7E676CAD0F225 +:102B0000A207C6768898186576D175D01249FF91CC +:102B10007551759175D00898D0EACAD0E5F0034C8C +:102B200071EAA2459AAD001C29F78D001CA9018D00 +:102B30000C18A9828D0D188D0E18AD001829600A89 +:102B40002A2A2A0948857849608577A200A000A929 +:102B5000009599E8B9E0FE9599E8C8C005D0F0A9BC +:102B6000009599E8A9029599E8A9D59599E8A9024F +:102B70009599A9FFA2129D2B02CA10FAA20595A74A +:102B800095AE95CDCA10F7A90585ABA90685ACA968 +:102B9000FF85AD85B4A9058D3B02A9848D3A02A9B4 +:102BA0000F8D5602A90185F6A98885F7A9E08D4FFA +:102BB00002A9FF8D5002A901851C851D2063CB2031 +:102BC000FACE2059F2A9228565A9EB8566A90A8566 +:102BD00069A905856AA97320C1E6A91A8D0218A9F9 +:102BE000008D00182080E758AD001829E58D0018E9 +:102BF000AD5502F00AA9008D550285672046C158DF +:102C0000A57CF0034C5BE858A90E8572A900856F7E +:102C10008570A672BD2B02C9FFF010293F85822066 +:102C200093DFAABD5B022901AAF66FC67210E3A06A +:102C300004B9000010052901AAF66F8810F378ADD9 +:102C4000001C29F748A57F8586A900857FA56FF020 +:102C50000BA51CF0032013D368090848E67FA57074 +:102C6000F00BA51DF0032013D368090048A5868545 +:102C70007F68AE6C02F021AD001CE080D0034C8B6D +:102C8000ECAE05183012A2A08E0518CE6C02D0084A +:102C90004D6D02A2108E6C028D001C4CFFEBA90042 +:102CA0008583A90120E2D1A90020C8D4A682A90069 +:102CB0009D44022093DFAAA57F9D5B02A90120F11C +:102CC000CFA90420F1CFA90120F1CF20F1CFAD721F +:102CD0000220F1CFA90020F1CF2059ED2093DF0A87 +:102CE000AAD699D699A90020F1CFA90120F1CF2029 +:102CF000F1CF20CEC6902CAD720220F1CFAD730281 +:102D000020F1CF2059EDA90020F1CFD0DD2093DFB5 +:102D10000AAAA9009599A988A4828D540299F20063 +:102D2000A58560AD720220F1CFAD730220F1CF20F6 +:102D300059ED2093DF0AAAD699D699A90020F1CFA0 +:102D400020F1CF20F1CF2093DF0AA8B99900A68205 +:102D50009D4402DE44024C0DEDA000B9B10220F109 +:102D6000CFC8C01BD0F5602037D1F001608585A4A5 +:102D700082B94402F008A98099F200A58560482034 +:102D8000EAEC686020D1C12042D0A9408DF9022030 +:102D9000B7EEA9008D920220ACC5D03DA900858177 +:102DA000AD85FE858020E5EDA9008DF90220FFEEBE +:102DB0004C94C1C8B19448C8B19448A013B194F0E0 +:102DC0000A8580C8B194858120E5ED688581688594 +:102DD0008020E5ED2004C6F0C3A000B19430D420DB +:102DE000B6C84CD4ED205FD52090EF2075D4A90053 +:102DF00020C8D42037D185802037D18581A580D0C7 +:102E0000034C27D22090EF204DD44CEEED2012C37E +:102E1000A5E21005A9334CC8C12901857F2000C156 +:102E2000A57F0AAAAC7B02CC7402F01AB900029505 +:102E300012B9010295132007D3A901858020C6C8C5 +:102E40002005F04C56EE2042D0A67FBD0101CDD525 +:102E5000FEF0034C72D520B7EEA5F9A80AAAAD88FA +:102E6000FE9599AE7A02A91B206EC6A012A67FAD70 +:102E7000D5FE9D01018A0AAAB5129194C8B5139195 +:102E800094C8C8A9329194C8ADD5FE9194A002917E +:102E90006DAD85FE85802093EFA90185812093EF9C +:102EA00020FFEE2005F0A001A9FF916D2064D4C69B +:102EB000812060D44C94C120D1F0A000A912916D62 +:102EC000C898916DC8C8C8A900856F85708571982C +:102ED0004A4A204BF2916DC8AA38266F2670267197 +:102EE000CAD0F6B56F916DC8E8E00390F6C0909037 +:102EF000D64C75D02093DFAABD5B022901857FA443 +:102F00007FB95102D00160A900995102203AEFA582 +:102F10007F0A4820A5F06818690120A5F0A580481F +:102F2000A90185800A0A856D2020F2E680A580CD62 +:102F3000D7FE90F06885804C8AD5200FF1AA20DF5B +:102F4000F0A6F9BDE0FE856EA900856D60A67FBD87 +:102F5000FA028D7202BDFC028D73026020F1EF2037 +:102F6000CFEF38D022B16D1DE9EF916D2088EFA42D +:102F70006F18B16D6901916DA580CD85FEF03BFEA6 +:102F8000FA02D003FEFC0260A67FA9019D510260F7 +:102F900020F1EF20CFEFF036B16D5DE9EF916D20BC +:102FA00088EFA46FB16D38E901916DA580CD85FEE4 +:102FB000F00BBDFA02D003DEFC02DEFA02BDFC0219 +:102FC000D00CBDFA02C903B005A97220C7E6602083 +:102FD00011F098856FA5814A4A4A38656FA8A58186 +:102FE0002907AAB16D3DE9EF6001020408102040F5 +:102FF00080A9FF2CF902F00C100A7008A9008DF9C5 +:10300000024C8AD560203AEFA00098916DC8D0FBA1 +:1030100060A56F48A57048A67FB5FFF005A974208C +:1030200048E6200FF1856F8A0A8570AAA580DD9D8C +:1030300002F00BE88670DD9D02F003205BF0A570C6 +:10304000A67F9D9B020A0A1869A1856DA9026900E5 +:10305000856EA00068857068856F60A66F20DFF0C0 +:10306000A57FAA0A1D9B0249012903857020A5F0AE +:10307000A5F90AAAA5800A0A9599A5700A0AA8A125 +:103080009999A102A9008199F699C8982903D0EFCE +:10309000A670A5809D9D02ADF902D0034C8AD5098A +:1030A000808DF90260A8B99D02F02548A900999D7C +:1030B00002A5F90AAA680A0A9599980A0AA8B9A164 +:1030C000028199A90099A102F699C8982903D0EE26 +:1030D00060A57F0AAAA9009D9D02E89D9D0260B59A +:1030E000A7C9FFD0258A48208ED2AA1005A9702032 +:1030F000C8C186F968A88A098099A7000AAAAD857F +:10310000FE9506A90095074C86D5290F85F960A97B +:1031100006A67FD00318690760200FF1AA60203E41 +:10312000DEA903856FA9010DF9028DF902A56F488B +:103130002011F068856FB16DD039A580CD85FEF086 +:1031400019901CE680A580CDD7FED0E1AE85FECAE1 +:103150008680A9008581C66FD0D3A97220C8C1C658 +:1031600080D0CAAE85FEE88680A9008581C66FD072 +:10317000BCF0E7A5811865698581A580204BF28D9B +:103180004E028D4D02C581B00C38A581ED4E0285F1 +:1031900081F002C68120FAF1F0034C90EFA900857E +:1031A0008120FAF1D0F44CF5F1A9010DF9028DF965 +:1031B00002A58648A9018586AD85FE38E58685800D +:1031C0009009F0072011F0B16DD01BAD85FE186598 +:1031D000868580E686CDD7FE9005A9672045E62046 +:1031E00011F0B16DF0D2688586A900858120FAF1D1 +:1031F000F0034C90EFA9712045E62011F09848208B +:1032000020F2A580204BF28D4E0268856FA581CDFE +:103210004E02B00920D5EFD006E681D0F0A90060BB +:10322000A56F48A900856FAC86FE88A207B16D3DE9 +:10323000E9EFF002E66FCA10F488D0EFB16DC56F08 +:10324000D00468856F60A9712045E6AED6FEDDD654 +:10325000FECAB0FABDD1FE6060A96F8D021C29F0D4 +:103260008D001CAD0C1C29FE090E09E08D0C1CA95B +:10327000418D0B1CA9008D061CA93A8D071C8D05DC +:103280001CA97F8D0E1CA9C08D0D1C8D0E1CA9FFC5 +:10329000853E8551A9088539A9078547A905856215 +:1032A000A9FA8563A9C88564A904855EA904855F18 +:1032B000BA8649AD041CAD0C1C090E8D0C1CA00572 +:1032C000B90000102EC9D0D004984C70F32901F039 +:1032D00007843FA90F4C69F9AA853DC53EF00A2035 +:1032E0007EF9A53D853E4C9CF9A52030030A1009C6 +:1032F0004C9CF98810CA4C9CF9A9208520A0058413 +:103300003F2093F3301AC63F10F7A4412095F3A550 +:1033100042854A064AA9608520B13285224C9CF933 +:103320002901C53DD0E0A522F01238F132F00D4957 +:10333000FF8542E642A53F85414C06F3A204B13227 +:103340008540DDD6FECAB0FABDD1FE85438A0A0AA1 +:103350000A0A0A8544AD001C299F05448D001CA65D +:103360003DA545C940F015C960F0034CB1F3A53F38 +:103370001869038531A90085306C3000A96085206B +:10338000AD001C29FC8D001CA9A4854AA901852239 +:103390004C69F9A43FB90000481010297885459878 +:1033A0000A69068532981869038531A0008430685F +:1033B00060A25A864BA200A95285242056F550FEE1 +:1033C000B8AD011CC524D03F50FEB8AD011C9525F9 +:1033D000E8E007D0F32097F4A004A900591600886C +:1033E00010FAC900D038A63EA5189522A545C930C7 +:1033F000F01EA53E0AA8B91200C516D01EB91300CA +:10340000C517D0174C23F4C64BD0B0A9022069F9D8 +:10341000A5168512A5178513A9012CA90B2CA9099E +:103420004C69F9A97F854CA519186902C54390021A +:10343000E543854DA205863FA2FF2093F310448506 +:10344000442901C53ED03CA000B132C540D034A5CE +:1034500045C960F00CA00138B132E54D1003186584 +:1034600043C54CB01E48A545F01468C9099014C95D +:103470000CB010854CA53FAA69038531D00568C9F9 +:103480000690F0C63F10B38A10034C9CF9863F208B +:1034900093F3A5454CCAF4A53048A53148A9248525 +:1034A00030A9008531A900853420E6F7A555851897 +:1034B000A5548519A553851A20E6F7A5528517A5A9 +:1034C00053851668853168853060C900F0034C6EFD +:1034D000F5200AF550FEB8AD011C9130C8D0F5A01A +:1034E000BA50FEB8AD011C990001C8D0F420E0F834 +:1034F000A538C547F005A9044C69F920E9F5C53A96 +:10350000F003A9052CA9014C69F92010F54C56F5DA +:10351000A53D0AAAB5128516B5138517A000B132CC +:103520008518C8B1328519A90045164517451845B3 +:1035300019851A2034F9A25A2056F5A00050FEB879 +:10354000AD011CD92400D006C8C008D0F060CAD094 +:10355000E7A9024C69F9A9D08D0518A9032C051813 +:1035600010F12C001C30F6AD011CB8A00060C91091 +:10357000F0034C91F620E9F5853AAD001C2910D0F6 +:1035800005A9084C69F9208FF72010F5A20950FE13 +:10359000B8CAD0FAA9FF8D031CAD0C1C291F09C0A5 +:1035A0008D0C1CA9FFA2058D011CB850FEB8CAD015 +:1035B000FAA0BBB9000150FEB88D011CC8D0F4B10F +:1035C0003050FEB88D011CC8D0F550FEAD0C1C0962 +:1035D000E08D0C1CA9008D031C20F2F5A43FB9005E +:1035E0000049309900004CB1F3A900A85130C8D06F +:1035F000FB60A900852E8530854FA531854EA90138 +:103600008531852FA9BB8534853620E6F7A55285FF +:1036100038A436A553912EC8A554912EC8A555910E +:103620002EC8843620E6F7A436A552912EC8A5539D +:10363000912EC8F00EA554912EC8A555912EC88480 +:1036400036D0E1A5549130C8A5559130C8843620B4 +:10365000E6F7A436A5529130C8A5539130C8A554B9 +:103660009130C8A5559130C88436C0BB90E1A945BA +:10367000852EA531852FA0BAB130912E88D0F9B111 +:1036800030912EA2BBBD00019130C8E8D0F7865022 +:1036900060C920F0034CCAF620E9F5853A208FF77F +:1036A000200AF5A0BBB9000150FEB84D011CD01591 +:1036B000C8D0F2B13050FEB84D011CD008C8C0FDD2 +:1036C000D0F14C18F4A9074C69F92010F54C18F406 +:1036D000A9008557855AA434A55229F04A4A4A4A76 +:1036E000AABD7FF70A0A0A8556A552290FAABD7FEF +:1036F000F76A66576A6657290705569130C8A55379 +:1037000029F04A4A4A4AAABD7FF70A05578557A5B4 +:1037100053290FAABD7FF72A2A2A2A85582A290168 +:1037200005579130C8A55429F04A4A4A4AAABD7F94 +:10373000F7186A05589130C86A29808559A5542917 +:103740000FAABD7FF70A0A297C05598559A5552975 +:10375000F04A4A4A4AAABD7FF76A665A6A665A6AB6 +:10376000665A290305599130C8D004A52F8531A583 +:1037700055290FAABD7FF7055A9130C88434600AD5 +:103780000B12130E0F161709191A1B0D1D1E15A962 +:10379000008530852E8536A9BB85348550A53185B9 +:1037A0002FA9018531A5478552A436B12E8553C86E +:1037B000B12E8554C8B12E8555C8843620D0F6A4C4 +:1037C00036B12E8552C8F011B12E8553C8B12E8561 +:1037D00054C8B12E8555C8D0E1A53A8553A90085B6 +:1037E0005485554CD0F6A434B13029F84A4A4A855C +:1037F00056B13029070A0A8557C8D006A54E85312B +:10380000A44FB13029C02A2A2A05578557B130293B +:103810003E4A8558B13029010A0A0A0A8559C8B1B9 +:103820003029F04A4A4A4A05598559B130290F0AC8 +:10383000855AC8B1302980182A2A2901055A855A83 +:10384000B130297C4A4A855BB13029030A0A0A85CE +:103850005CC8D006A54E8531A44FB13029E02A2A94 +:103860002A2A055C855CB130291F855DC88434A691 +:1038700056BDA0F8A6571DC0F88552A658BDA0F8A1 +:10388000A6591DC0F88553A65ABDA0F8A65B1DC059 +:10389000F88554A65CBDA0F8A65D1DC0F8855560EE +:1038A000FFFFFFFFFFFFFFFFFF800010FFC0405042 +:1038B000FFFF2030FFF06070FF90A0B0FFD0E0FF6E +:1038C000FFFFFFFFFFFFFFFFFF080001FF0C0405E4 +:1038D000FFFF0203FF0F0607FF090A0BFF0D0EFF94 +:1038E000A9008534852E8536A901854EA9BA854F54 +:1038F000A531852F20E6F7A5528538A436A553912A +:103900002EC8A554912EC8A555912EC8843620E600 +:10391000F7A436A552912EC8F011A553912EC8A533 +:1039200054912EC8A555912EC8D0E1A553853AA52E +:103930002F853160A531852FA9008531A9248534D3 +:10394000A5398552A51A8553A5198554A5188555FD +:1039500020D0F6A5178552A5168553A90085548554 +:103960005520D0F6A52F853160A43F990000A550C1 +:10397000F00320F2F5208FF9A6499A4CBEF2A9A0D7 +:103980008520AD001C09048D001CA93C854860A65B +:103990003EA52009108520A9FF854860AD071C8D34 +:1039A000051CAD001C2910C51E851EF004A901854B +:1039B0001CADFE02F015C902D007A9008DFE02F071 +:1039C0000A854AA9028DFE024C2EFAA63E3007A5B2 +:1039D00020A8C920D0034CBEFAC648D01D981004B8 +:1039E000297F85202910F012AD001C29FB8D001CB9 +:1039F000A9FF853EA9008520F0DC982940D0034C22 +:103A0000BEFA6C6200A54A100549FF186901C56439 +:103A1000B00AA93B8562A9FA8563D012E55EE55E2E +:103A20008561A55E8560A97B8562A9FA8563A54A43 +:103A30001031E64AAE001CCA4C69FAA54AD0EFA97B +:103A40004E8562A9FA8563A90585604CBEFAC660F9 +:103A5000D06CA52029BF8520A9058562A9FA8563B8 +:103A60004CBEFAC64AAE001CE88A2903854BAD005D +:103A70001C29FC054B8D001C4CBEFA38AD071CE51B +:103A80005F8D051CC660D00CA55E8560A997856218 +:103A9000A9FA85634C2EFAC661D0F9A9A58562A959 +:103AA000FA8563D0EFAD071C18655F8D051CC660F5 +:103AB000D0E2A94E8562A9FA8563A9058560AD0C9F +:103AC0001C29FD8D0C1C60A551102AA63DA96095EE +:103AD00020A90195228551A9A4854AAD001C29FC85 +:103AE0008D001CA90A8D2006A9A08D2106A90F8D85 +:103AF00022064C9CF9A000D132F00591324C9CF981 +:103B0000AD001C2910D005A9084CD3FD20A3FD2031 +:103B1000C3FDA9558D011C20C3FD2000FE2056F5D4 +:103B2000A9400D0B188D0B18A9628D0618A9008DE0 +:103B300007188D0518A000A2002C001C30FB2C00DB +:103B40001C10FBAD04182C001C1011AD0D180A1030 +:103B5000F5E8D0EFC8D0ECA9024CD3FD8671847291 +:103B6000A200A000AD04182C001C3011AD0D180AE5 +:103B700010F5E8D0EFC8D0ECA9024CD3FD388AE5A7 +:103B800071AA857098E572A88571100B49FFA88A03 +:103B900049FFAAE8D001C898D004E0049018067044 +:103BA000267118A5706D21068D2106A5716D22065E +:103BB0008D22064C0CFBA200A000B8AD001C100E1C +:103BC00050F9B8E8D0F5C8D0F2A9034CD3FD8A0A61 +:103BD0008D2506982A8D2406A9BF2D0B188D0B184C +:103BE000A9668D2606A643A00098186D26069001AA +:103BF000C8C8CAD0F549FF386900186D2506B0035A +:103C0000CE2406AA9849FF386900186D24061005CD +:103C1000A9044CD3FDA88AA20038E543B00388303C +:103C200003E8D0F58E2606E004B005A9054CD3FDC7 +:103C30001865438D2706A9008D2806A000A63DA57E +:103C400039990003C8C8AD2806990003C8A5519941 +:103C50000003C8B513990003C8B512990003C8A999 +:103C60000F990003C8990003C8A90059FA0259FB2B +:103C70000259FC0259FD0299F902EE2806AD280608 +:103C8000C54390BB9848E88A9D0005E8D0FAA9038F +:103C900085312030FE68A88820E5FD20F5FDA905C6 +:103CA000853120E9F5853A208FF7A9008532200E6D +:103CB000FEA9FF8D011CA20550FEB8CAD0FAA20AC7 +:103CC000A43250FEB8B900038D011CC8CAD0F3A2BB +:103CD0000950FEB8A9558D011CCAD0F5A9FFA2054F +:103CE00050FEB88D011CCAD0F7A2BB50FEB8BD0073 +:103CF000018D011CE8D0F4A00050FEB8B1308D0158 +:103D00001CC8D0F5A955AE260650FEB88D011CCAB8 +:103D1000D0F7A53218690A8532CE2806D09350FE16 +:103D2000B850FEB82000FEA9C88D2306A900853032 +:103D3000A9038531A5438D28062056F5A20AA000C7 +:103D400050FEB8AD011CD130D00EC8CAD0F218A5B3 +:103D500030690A85304C62FDCE2306D0CFA9064CCF +:103D6000D3FD2056F5A0BB50FEB8AD011CD9000113 +:103D7000D0E6C8D0F2A2FC50FEB8AD011CD90005B7 +:103D8000D0D6C8CAD0F1CE2806D0AEE651A551C9CA +:103D900024B0034C9CF9A9FF8551A9008550A901C5 +:103DA0004C69F9AD0C1C291F09C08D0C1CA9FF8D95 +:103DB000031C8D011CA228A00050FEB888D0FACAAE +:103DC000D0F760AE2106AC220650FEB8CAD0FA8801 +:103DD00010F760CE2006F0034C9CF9A0FF8451C878 +:103DE00084504C69F9B9000399450388D0F7AD00B8 +:103DF000038D450360A044B9BB0191308810F86081 +:103E0000AD0C1C09E08D0C1CA9008D031C60AD0CD1 +:103E10001C291F09C08D0C1CA9FF8D031CA9558DE1 +:103E2000011CA228A00050FEB888D0FACAD0F760C2 +:103E3000A9008530852E8536A9BB8534A531852F0F +:103E4000A9018531A436B12E8552C8B12E8553C83B +:103E5000B12E8554C8B12E8555C8F008843620D0BF +:103E6000F64C44FE4CD0F6488A489848AD0D1829C7 +:103E700002F0032053E8AD0D1C0A100320B0F268D5 +:103E8000A868AA6840120404905649444D4255500F +:103E9000264352534E8405C1F81B5C07A3F08823C8 +:103EA0000DEDD0C8CACCCBE2E7C8CAC8EE51DD1CC4 +:103EB0009E1C5257414D445350554C4453505552FB +:103EC00045455253454C5147524C0800003F7FBF77 +:103ED000FF111213154104241F191201FFFF0100E5 +:103EE0000304050607070E6C65008D001C8D021C7F +:103EF0004C7DEA8AA205CAD0FDAA6020AEE94C9C9E +:103F0000E9AD0202C92DF00538E92BD0DA8523602E +:103F1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA01 +:103F2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1 +:103F3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE1 +:103F4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1 +:103F5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1 +:103F6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1 +:103F7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1 +:103F8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA91 +:103F9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA81 +:103FA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA71 +:103FB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA61 +:103FC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA51 +:103FD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA41 +:103FE000AAAA525352AAC6C88FF95FCD97CD000531 +:103FF0000305060509050C050F0501FFA0EA67FE8C +:00000001FF diff --git a/cores/c16/sd_card.v b/cores/c16/sd_card.v deleted file mode 100644 index 97b479b..0000000 --- a/cores/c16/sd_card.v +++ /dev/null @@ -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 -// -// 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://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 diff --git a/cores/c16/t65/T65.vhd b/cores/c16/t65/T65.vhd new file mode 100644 index 0000000..4a21d79 --- /dev/null +++ b/cores/c16/t65/T65.vhd @@ -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; diff --git a/cores/c16/t65/T65_ALU.vhd b/cores/c16/t65/T65_ALU.vhd new file mode 100644 index 0000000..d9d25e1 --- /dev/null +++ b/cores/c16/t65/T65_ALU.vhd @@ -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; diff --git a/cores/c16/t65/T65_MCode.vhd b/cores/c16/t65/T65_MCode.vhd new file mode 100644 index 0000000..3fd40d8 --- /dev/null +++ b/cores/c16/t65/T65_MCode.vhd @@ -0,0 +1,1052 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 302 minor timing fixes +-- Ver 301 Jump timing fixed +-- 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 + fix +-- +-- 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 +-- supported : inc, dec, phx, plx, phy, ply +-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8 +-- +-- File history : +-- +-- 0246 : First release +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T65_Pack.all; + +entity T65_MCode is + 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 T65_MCode; + +architecture rtl of T65_MCode is + + signal Branch : std_logic; + +begin + + with IR(7 downto 5) select + Branch <= not P(Flag_N) when "000", + P(Flag_N) when "001", + not P(Flag_V) when "010", + P(Flag_V) when "011", + not P(Flag_C) when "100", + P(Flag_C) when "101", + not P(Flag_Z) when "110", + P(Flag_Z) when others; + + process (IR, MCycle, P, Branch, Mode) + begin + LCycle <= "001"; + Set_BusA_To <= "001"; -- A + Set_Addr_To <= (others => '0'); + Write_Data <= (others => '0'); + Jump <= (others => '0'); + BAAdd <= "00"; + BreakAtNA <= '0'; + ADAdd <= '0'; + PCAdd <= '0'; + Inc_S <= '0'; + Dec_S <= '0'; + LDA <= '0'; + LDP <= '0'; + LDX <= '0'; + LDY <= '0'; + LDS <= '0'; + LDDI <= '0'; + LDALU <= '0'; + LDAD <= '0'; + LDBAL <= '0'; + LDBAH <= '0'; + SaveP <= '0'; + Write <= '0'; + AddY <= '0'; + + case IR(7 downto 5) is + when "100" => + --{{{ + case IR(1 downto 0) is + when "00" => + Set_BusA_To <= "011"; -- Y + Write_Data <= "011"; -- Y + when "10" => + Set_BusA_To <= "010"; -- X + Write_Data <= "010"; -- X + when others => + Write_Data <= "001"; -- A + end case; + --}}} + when "101" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) /= '1' or IR(2) /= '0' then + LDY <= '1'; + end if; + when "10" => + LDX <= '1'; + when others => + LDA <= '1'; + end case; + Set_BusA_To <= "000"; -- DI + --}}} + when "110" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDY <= '1'; + end if; + Set_BusA_To <= "011"; -- Y + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when "111" => + --{{{ + case IR(1 downto 0) is + when "00" => + if IR(4) = '0' then + LDX <= '1'; + end if; + Set_BusA_To <= "010"; -- X + when others => + Set_BusA_To <= "001"; -- A + end case; + --}}} + when others => + end case; + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + Set_BusA_To <= "000"; -- DI + end if; + + case IR(4 downto 0) is + when "00000" | "01000" | "01010" | "11000" | "11010" => + --{{{ + -- Implied + case IR is + when "00000000" => + -- BRK + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 2 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "101"; -- P + Write <= '1'; + when 4 => + Dec_S <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDDI <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + Jump <= "10"; -- DIDL + when others => + end case; + when "00100000" => + -- JSR + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Set_Addr_To <= "01"; -- S + Write_Data <= "111"; -- PCH + Write <= '1'; + when 3 => + Dec_S <= '1'; + Set_Addr_To <= "01"; -- S + Write_Data <= "110"; -- PCL + Write <= '1'; + when 4 => + Dec_S <= '1'; + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01000000" => + -- RTI + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + Set_BusA_To <= "000"; -- DI + when 4 => + LDP <= '1'; + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 5 => + Jump <= "10"; -- DIDL + when others => + end case; + when "01100000" => + -- RTS + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Inc_S <= '1'; + LDDI <= '1'; + Set_Addr_To <= "01"; -- S + when 4 => + Jump <= "10"; -- DIDL + when 5 => + Jump <= "01"; + when others => + end case; + when "00001000" | "01001000" | "01011010" | "11011010" => + -- PHP, PHA, PHY*, PHX* + LCycle <= "010"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case to_integer(unsigned(MCycle)) is + when 1 => + case IR(7 downto 4) is + when "0000" => + Write_Data <= "101"; -- P + when "0100" => + Write_Data <= "001"; -- A + when "0101" => + Write_Data <= "011"; -- Y + when "1101" => + Write_Data <= "010"; -- X + when others => + end case; + Write <= '1'; + Set_Addr_To <= "01"; -- S + when 2 => + Dec_S <= '1'; + when others => + end case; + when "00101000" | "01101000" | "01111010" | "11111010" => + -- PLP, PLA, PLY*, PLX* + LCycle <= "011"; + if Mode = "00" and IR(1) = '1' then + LCycle <= "001"; + end if; + case IR(7 downto 4) is + when "0010" => + LDP <= '1'; + when "0110" => + LDA <= '1'; + when "0111" => + if Mode /= "00" then + LDY <= '1'; + end if; + when "1111" => + if Mode /= "00" then + LDX <= '1'; + end if; + when others => + end case; + case to_integer(unsigned(MCycle)) is + when 0 => + SaveP <= '1'; + when 1 => + Set_Addr_To <= "01"; -- S + when 2 => + Inc_S <= '1'; + Set_Addr_To <= "01"; -- S + when 3 => + Set_BusA_To <= "000"; -- DI + when others => + end case; + when "10100000" | "11000000" | "11100000" => + -- LDY, CPY, CPX + -- Immediate + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + when "10001000" => + -- DEY + LDY <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "011"; -- Y + when others => + end case; + when "11001010" => + -- DEX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "010"; -- X + when others => + end case; + when "00011010" | "00111010" => + -- INC*, DEC* + if Mode /= "00" then + LDA <= '1'; -- A + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + when "00001010" | "00101010" | "01001010" | "01101010" => + -- ASL, ROL, LSR, ROR + LDA <= '1'; -- A + Set_BusA_To <= "001"; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10001010" | "10011000" => + -- TYA, TXA + LDA <= '1'; -- A + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + when others => + end case; + when "10101010" | "10101000" => + -- TAX, TAY + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "001"; -- A + when others => + end case; + when "10011010" => + -- TXS + case to_integer(unsigned(MCycle)) is + when 0 => + LDS <= '1'; + when 1 => + when others => + end case; + when "10111010" => + -- TSX + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Set_BusA_To <= "100"; -- S + when others => + end case; + + -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => + -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX + -- case to_integer(unsigned(MCycle)) is + -- when 1 => + -- when others => + -- end case; + when others => + case to_integer(unsigned(MCycle)) is + when 0 => + when others => + end case; + end case; + --}}} + + when "00001" | "00011" => + --{{{ + -- Zero Page Indexed Indirect (d,x) + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + BAAdd <= "01"; -- DB Inc + LDBAL <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "01001" | "01011" => + --{{{ + -- Immediate + LDA <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + when others => + end case; + + --}}} + + when "00010" | "10010" => + --{{{ + -- Immediate, KIL + LDX <= '1'; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + if IR = "10100010" then + -- LDX + Jump <= "01"; + else + -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end if; + when others => + end case; + --}}} + + when "00100" => + --{{{ + -- Zero Page + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + --}}} + + when "00101" | "00110" | "00111" => + --{{{ + -- Zero Page + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + when others => + end case; + else + LCycle <= "010"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 2 => + when others => + end case; + end if; + --}}} + + when "01100" => + --{{{ + -- Absolute + if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then + -- JMP + if IR(5) = '0' then + --LCycle <= "011"; + LCycle <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + when 2 => + Jump <= "10"; -- DIDL + when others => + end case; + else + --LCycle <= "101"; + LCycle <= "100"; -- mikej + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDDI <= '1'; + LDBAL <= '1'; + when 2 => + LDBAH <= '1'; + if Mode /= "00" then + Jump <= "10"; -- DIDL + end if; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + end if; + when 3 => + LDDI <= '1'; + if Mode = "00" then + Set_Addr_To <= "11"; -- BA + BAAdd <= "01"; -- DB Inc + else + Jump <= "01"; + end if; + when 4 => + Jump <= "10"; -- DIDL + when others => + end case; + end if; + else + LCycle <= "011"; + case to_integer(unsigned(MCycle)) is + when 0 => + if IR(7 downto 5) = "001" then + SaveP <= '1'; + end if; + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "01101" | "01110" | "01111" => + --{{{ + -- Absolute + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + Write <= '1'; + LDALU <= '1'; + SaveP <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + SaveP <= '0'; -- MIKEJ was 1 + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + LDBAH <= '1'; + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 3 => + when others => + end case; + end if; + --}}} + + when "10000" => + --{{{ + -- Relative + + -- This circuit dictates when the last + -- microcycle occurs for the branch depending on + -- whether or not the branch is taken and if a page + -- is crossed... + if (Branch = '1') then + + LCycle <= "011"; -- We're done @ T3 if branching...upper + -- level logic will stop at T2 if no page cross + -- (See the Break signal) + else + + LCycle <= "001"; + + end if; + + -- This decodes the current microcycle and takes the + -- proper course of action... + case to_integer(unsigned(MCycle)) is + + -- On the T1 microcycle, increment the program counter + -- and instruct the upper level logic to fetch the offset + -- from the Din bus and store it in the data latches. This + -- will be the last microcycle if the branch isn't taken. + when 1 => + + Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) + -- from microcycle T0. + + LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route + -- the Din bus to the memory data latch (DL) + -- so that the branch offset is fetched. + + -- In microcycle T2, tell the logic in the top level to + -- add the offset. If the most significant byte of the + -- program counter (i.e. the current "page") does not need + -- updating, we are done here...the Break signal at the + -- T65.vhd level takes care of that... + when 2 => + + Jump <= "11"; -- Tell the PC Jump logic to use relative mode. + + PCAdd <= '1'; -- This tells the PC adder to update itself with + -- the current offset recently fetched from + -- memory. + + -- The following is microcycle T3 : + -- The program counter should be completely updated + -- on this cycle after the page cross is detected. + -- We don't need to do anything here... + when 3 => + + + when others => null; -- Do nothing. + + end case; + --}}} + + when "10001" | "10011" => + --{{{ + -- Zero Page Indirect Indexed (d),y + LCycle <= "101"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + LDBAL <= '1'; + BAAdd <= "01"; -- DB Inc + Set_Addr_To <= "10"; -- AD + when 3 => + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 4 => + BAAdd <= "11"; -- BA Adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 5 => + when others => + end case; + --}}} + + when "10100" | "10101" | "10110" | "10111" => + --{{{ + -- Zero Page, X + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + Set_Addr_To <= "10"; -- AD + when 3 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 4 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "10"; -- AD + when 5 => + when others => + end case; + else + LCycle <= "011"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDAD <= '1'; + Set_Addr_To <= "10"; -- AD + when 2 => + ADAdd <= '1'; + -- Added this check for Y reg. use... + if (IR(3 downto 0) = "0110") then + AddY <= '1'; + end if; + + if IR(7 downto 5) = "100" then + Write <= '1'; + end if; + Set_Addr_To <= "10"; -- AD + when 3 => null; + when others => + end case; + end if; + --}}} + + when "11001" | "11011" => + --{{{ + -- Absolute Y + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "011"; -- Y + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + --}}} + + when "11100" | "11101" | "11110" | "11111" => + --{{{ + -- Absolute X + + if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then + -- Read-Modify-Write + LCycle <= "110"; + case to_integer(unsigned(MCycle)) is + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + Set_BusA_To <= "010"; -- X + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + Set_Addr_To <= "11"; -- BA + when 4 => + LDDI <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 5 => + LDALU <= '1'; + SaveP <= '1'; + Write <= '1'; + Set_Addr_To <= "11"; -- BA + when 6 => + when others => + end case; + else + LCycle <= "100"; + if IR(7 downto 6) /= "10" then + LDA <= '1'; + end if; + case to_integer(unsigned(MCycle)) is + when 0 => + when 1 => + Jump <= "01"; + LDBAL <= '1'; + when 2 => + Jump <= "01"; + -- mikej + -- special case 0xBE which uses Y reg as index!! + if (IR = "10111110") then + Set_BusA_To <= "011"; -- Y + else + Set_BusA_To <= "010"; -- X + end if; + BAAdd <= "10"; -- BA Add + LDBAH <= '1'; + Set_Addr_To <= "11"; -- BA + when 3 => + BAAdd <= "11"; -- BA adj + if IR(7 downto 5) = "100" then + Write <= '1'; + else + BreakAtNA <= '1'; + end if; + Set_Addr_To <= "11"; -- BA + when 4 => + when others => + end case; + end if; + --}}} + when others => + end case; + end process; + + process (IR, MCycle) + begin + -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC + -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC + case IR(1 downto 0) is + when "00" => + --{{{ + case IR(4 downto 2) is + when "000" | "001" | "011" => + case IR(7 downto 5) is + when "110" | "111" => + -- CP + ALU_Op <= "0110"; + when "101" => + -- LD + ALU_Op <= "0101"; + when "001" => + -- BIT + ALU_Op <= "1100"; + when others => + -- NOP/ST + ALU_Op <= "0100"; + end case; + when "010" => + case IR(7 downto 5) is + when "111" | "110" => + -- IN + ALU_Op <= "1111"; + when "100" => + -- DEY + ALU_Op <= "1110"; + when others => + -- LD + ALU_Op <= "1101"; + end case; + when "110" => + case IR(7 downto 5) is + when "100" => + -- TYA + ALU_Op <= "1101"; + when others => + ALU_Op <= "----"; + end case; + when others => + case IR(7 downto 5) is + when "101" => + -- LD + ALU_Op <= "1101"; + when others => + ALU_Op <= "0100"; + end case; + end case; + --}}} + when "01" => -- OR + --{{{ + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + --}}} + when "10" => + --{{{ + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + case IR(7 downto 5) is + when "000" => + if IR(4 downto 2) = "110" then + -- INC + ALU_Op <= "1111"; + end if; + when "001" => + if IR(4 downto 2) = "110" then + -- DEC + ALU_Op <= "1110"; + end if; + when "100" => + if IR(4 downto 2) = "010" then + -- TXA + ALU_Op <= "0101"; + else + ALU_Op <= "0100"; + end if; + when others => + end case; + --}}} + when others => + --{{{ + case IR(7 downto 5) is + when "100" => + ALU_Op <= "0100"; + when others => + if MCycle = "000" then + ALU_Op(3) <= '0'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + else + ALU_Op(3) <= '1'; + ALU_Op(2 downto 0) <= IR(7 downto 5); + end if; + end case; + --}}} + end case; + end process; + +end; diff --git a/cores/c16/t65/T65_Pack.vhd b/cores/c16/t65/T65_Pack.vhd new file mode 100644 index 0000000..f8d603c --- /dev/null +++ b/cores/c16/t65/T65_Pack.vhd @@ -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; diff --git a/cores/c16/user_io.v b/cores/c16/user_io.v index e679e00..e140818 100644 --- a/cores/c16/user_io.v +++ b/cores/c16/user_io.v @@ -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 +// +// 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 -// -// 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 . +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // // 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