From b136cdf02648632c3e115e5af21eee98035217df Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Sun, 17 May 2020 21:38:02 +0200 Subject: [PATCH] C16: update C1541 from C64 --- cores/c16/c1541/c1541_logic.vhd | 23 +++--- cores/c16/c1541/c1541_sd.vhd | 2 +- cores/c16/c1541/gcr_floppy.vhd | 46 ++++++----- cores/c16/c1541/via6522.vhd | 132 +++++++++++++++++++------------- 4 files changed, 118 insertions(+), 85 deletions(-) diff --git a/cores/c16/c1541/c1541_logic.vhd b/cores/c16/c1541/c1541_logic.vhd index bfba5b3..4fffbb2 100644 --- a/cores/c16/c1541/c1541_logic.vhd +++ b/cores/c16/c1541/c1541_logic.vhd @@ -170,14 +170,15 @@ begin uc1_ca1_i <= not sb_atn_in; -- PA uc1_pa_i(0) <= tr00_sense_n; - uc1_pa_i(7 downto 1) <= (others => '0'); -- NC + uc1_pa_i(7 downto 1) <= (others => '1'); -- NC + -- PB - uc1_pb_i(0) <= not (sb_data_in and sb_data_oe); - sb_data_oe <= not (uc1_pb_o(1) or uc1_pb_oe_n(1)) and not atn; + uc1_pb_i(1) <= '1'; + sb_data_oe <= not (uc1_pb_o(1) or uc1_pb_oe_n(1)) and not atn; uc1_pb_i(2) <= not (sb_clk_in and sb_clk_oe); - sb_clk_oe <= not (uc1_pb_o(3) or uc1_pb_oe_n(3)); - + sb_clk_oe <= not (uc1_pb_o(3) or uc1_pb_oe_n(3)); + uc1_pb_i(4 downto 3) <= "11"; -- NC atna <= uc1_pb_o(4) or uc1_pb_oe_n(4); uc1_pb_i(6 downto 5) <= DEVICE_SELECT xor ds; -- allows override uc1_pb_i(7) <= not sb_atn_in; @@ -314,10 +315,10 @@ begin port_b_i => uc1_pb_i, ca1_i => uc1_ca1_i, - ca2_i => '0', + ca2_i => '1', - cb1_i => '0', - cb2_i => '0', + cb1_i => '1', + cb2_i => '1', irq => uc1_irq ); @@ -353,13 +354,13 @@ begin ca1_i => uc3_ca1_i, ca2_o => uc3_ca2_o, - ca2_i => '0', + ca2_i => '1', ca2_t => uc3_ca2_oe, - cb1_i => '0', + cb1_i => '1', cb2_o => uc3_cb2_o, - cb2_i => '0', + cb2_i => '1', cb2_t => uc3_cb2_oe, irq => uc3_irq diff --git a/cores/c16/c1541/c1541_sd.vhd b/cores/c16/c1541/c1541_sd.vhd index 7b5649b..cc5b8e6 100644 --- a/cores/c16/c1541/c1541_sd.vhd +++ b/cores/c16/c1541/c1541_sd.vhd @@ -199,7 +199,7 @@ port map mode => mode, -- read/write -- stp => stp, -- stepper motor control mtr => mtr, -- stepper motor on/off --- freq => freq, -- motor (gcr_bit) frequency + freq => freq, -- motor (gcr_bit) frequency sync_n => sync_n, -- reading SYNC bytes byte_n => byte_n, -- byte ready diff --git a/cores/c16/c1541/gcr_floppy.vhd b/cores/c16/c1541/gcr_floppy.vhd index 9b125a2..f6b5427 100644 --- a/cores/c16/c1541/gcr_floppy.vhd +++ b/cores/c16/c1541/gcr_floppy.vhd @@ -24,7 +24,7 @@ port( 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 + 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 @@ -43,6 +43,7 @@ end gcr_floppy; architecture struct of gcr_floppy is signal bit_clk_en : std_logic; +signal bit_clk_div : std_logic_vector(7 downto 0); 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'; @@ -134,7 +135,7 @@ with nibble select gcr_bit <= gcr_nibble(to_integer(unsigned(gcr_bit_cnt))); -sector_max <= "10100" when track_num < std_logic_vector(to_unsigned(18,6)) else +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" ; @@ -158,27 +159,33 @@ with gcr_nibble_out select X"D" when "11101",--"10111", X"E" when "11110",--"01111", X"F" when others; --"10101", - + +with freq select + bit_clk_div <= x"67" when "11", + x"6F" when "10", + x"77" when "01", + x"7F" when others; + 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 + if bit_clk_cnt = bit_clk_div 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 @@ -187,9 +194,7 @@ begin end if; end if; end if; - end if; - end if; end process; @@ -201,11 +206,11 @@ begin if old_track /= track_num then sector <= (others => '0'); --reset sector number on track change - else if bit_clk_en = '1' then + elsif 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'; @@ -220,9 +225,9 @@ begin 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'); @@ -230,18 +235,18 @@ begin 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'); @@ -292,17 +297,17 @@ begin 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; @@ -318,11 +323,10 @@ begin else ram_we <= '0'; end if; - + end if; end if; end if; - end if; end process; end struct; diff --git a/cores/c16/c1541/via6522.vhd b/cores/c16/c1541/via6522.vhd index 7c982bc..ae2bb04 100644 --- a/cores/c16/c1541/via6522.vhd +++ b/cores/c16/c1541/via6522.vhd @@ -97,8 +97,11 @@ architecture Gideon of via6522 is signal serport_en : std_logic; signal ser_cb2_o : std_logic; signal hs_cb2_o : std_logic; - signal trigger_serial: std_logic; - + signal cb1_t_int : std_logic; + signal cb1_o_int : std_logic; + signal cb2_t_int : std_logic; + signal cb2_o_int : std_logic; + alias ca2_event : std_logic is irq_events(0); alias ca1_event : std_logic is irq_events(1); alias serial_event : std_logic is irq_events(2); @@ -137,7 +140,8 @@ architecture Gideon of via6522 is alias ca1_edge_select : std_logic is pcr(0); signal ira, irb : std_logic_vector(7 downto 0) := (others => '0'); - + + signal write_t1c_l : std_logic; signal write_t1c_h : std_logic; signal write_t2c_h : std_logic; @@ -154,6 +158,7 @@ architecture Gideon of via6522 is begin irq <= irq_out; + write_t1c_l <= '1' when (addr = X"4" or addr = x"6") and wen='1' and falling = '1' else '0'; write_t1c_h <= '1' when addr = X"5" and wen='1' and falling = '1' else '0'; write_t2c_h <= '1' when addr = X"9" and wen='1' and falling = '1' else '0'; @@ -163,8 +168,13 @@ begin cb2_event <= (cb2_c xor cb2_d) and (cb2_d xor cb2_edge_select); ca2_t <= ca2_is_output; - cb2_t <= cb2_is_output when serport_en='0' else shift_dir; - cb2_o <= hs_cb2_o when serport_en='0' else ser_cb2_o; + cb2_t_int <= cb2_is_output when serport_en='0' else shift_dir; + cb2_o_int <= hs_cb2_o when serport_en='0' else ser_cb2_o; + + cb1_t <= cb1_t_int; + cb1_o <= cb1_o_int; + cb2_t <= cb2_t_int; + cb2_o <= cb2_o_int; with ca2_out_mode select ca2_o <= ca2_handshake_o when "00", @@ -205,8 +215,16 @@ begin -- CA1/CA2/CB1/CB2 edge detect flipflops ca1_c <= To_X01(ca1_i); ca2_c <= To_X01(ca2_i); - cb1_c <= To_X01(cb1_i); - cb2_c <= To_X01(cb2_i); + if cb1_t_int = '0' then + cb1_c <= To_X01(cb1_i); + else + cb1_c <= cb1_o_int; + end if; + if cb2_t_int = '0' then + cb2_c <= To_X01(cb2_i); + else + cb2_c <= cb2_o_int; + end if; ca1_d <= ca1_c; ca2_d <= ca2_c; @@ -259,10 +277,6 @@ begin -- Interrupt logic irq_flags <= irq_flags or irq_events; - if falling = '1' then - trigger_serial <= '0'; - end if; - -- Writes -- if wen='1' and falling = '1' then last_data <= data_in; @@ -309,9 +323,6 @@ begin when X"A" => -- Serial port serial_flag <= '0'; - if shift_active = '0' then - trigger_serial <= '1'; - end if; when X"B" => -- ACR (Auxiliary Control Register) acr <= data_in; @@ -343,6 +354,9 @@ begin when X"0" => -- ORB --Port B reads its own output register for pins set to output. data_out <= (pio_i.prb and pio_i.ddrb) or (irb and not pio_i.ddrb); + if tmr_a_output_en='1' then + data_out(7) <= timer_a_out; + end if; when X"1" => -- ORA data_out <= ira; when X"2" => -- DDRB @@ -400,7 +414,6 @@ begin when X"A" => -- SR serial_flag <= '0'; - trigger_serial <= '1'; when others => null; @@ -419,7 +432,6 @@ begin cb2_pulse_o <= '1'; timer_a_latch <= latch_reset_pattern; timer_b_latch <= latch_reset_pattern; - trigger_serial <= '0'; end if; end if; end process; @@ -437,8 +449,8 @@ begin -- Timer A tmr_a: block signal timer_a_reload : std_logic; - signal timer_a_oneshot_trig : std_logic; signal timer_a_toggle : std_logic; + signal timer_a_may_interrupt : std_logic; begin process(clock) begin @@ -448,8 +460,11 @@ begin if timer_a_reload = '1' then timer_a_count <= timer_a_latch; + if write_t1c_l = '1' then + timer_a_count(7 downto 0) <= data_in; + end if; timer_a_reload <= '0'; - timer_a_oneshot_trig <= '0'; + timer_a_may_interrupt <= timer_a_may_interrupt and tmr_a_freerun; else if timer_a_count = X"0000" then -- generate an event if we were triggered @@ -461,29 +476,29 @@ begin end if; if rising = '1' then - if timer_a_event = '1' then + if timer_a_event = '1' and tmr_a_output_en = '1' then timer_a_toggle <= not timer_a_toggle; end if; end if; if write_t1c_h = '1' then - timer_a_toggle <= '0'; + timer_a_may_interrupt <= '1'; + timer_a_toggle <= not tmr_a_output_en; timer_a_count <= data_in & timer_a_latch(7 downto 0); timer_a_reload <= '0'; - timer_a_oneshot_trig <= '1'; end if; if reset='1' then + timer_a_may_interrupt <= '0'; timer_a_toggle <= '1'; timer_a_count <= latch_reset_pattern; timer_a_reload <= '0'; - timer_a_oneshot_trig <= '0'; end if; end if; end process; timer_a_out <= timer_a_toggle; - timer_a_event <= rising and timer_a_reload and (tmr_a_freerun or timer_a_oneshot_trig); + timer_a_event <= rising and timer_a_reload and timer_a_may_interrupt; end block tmr_a; @@ -559,41 +574,56 @@ begin end block tmr_b; ser: block + signal trigger_serial: std_logic; signal shift_clock_d : std_logic; signal shift_clock : std_logic; signal shift_tick_r : std_logic; signal shift_tick_f : std_logic; + signal shift_timer_tick : std_logic; signal cb2_c : std_logic := '0'; signal bit_cnt : integer range 0 to 7; signal shift_pulse : std_logic; begin - process(shift_active, timer_b_tick, shift_clk_sel, shift_clock, shift_clock_d) + process(shift_active, timer_b_tick, shift_clk_sel, shift_clock, shift_clock_d, shift_timer_tick) begin case shift_clk_sel is when "10" => shift_pulse <= '1'; when "00"|"01" => - shift_pulse <= timer_b_tick; + shift_pulse <= shift_timer_tick; when others => shift_pulse <= shift_clock and not shift_clock_d; end case; - + if shift_active = '0' then - shift_pulse <= '0'; + -- Mode 0 still loads the shift register to external pulse (MMBEEB SD-Card interface uses this) + if shift_mode_control = "000" then + shift_pulse <= shift_clock and not shift_clock_d; + else + shift_pulse <= '0'; + end if; end if; + end process; + process(clock) begin if rising_edge(clock) then + + cb2_c <= To_X01(cb2_i); + if rising = '1' then - cb2_c <= To_X01(cb2_i); if shift_active='0' then - shift_clock <= '1'; + if shift_mode_control = "000" then + shift_clock <= To_X01(cb1_i); + else + shift_clock <= '1'; + end if; elsif shift_clk_sel = "11" then shift_clock <= To_X01(cb1_i); elsif shift_pulse = '1' then @@ -602,55 +632,53 @@ begin shift_clock_d <= shift_clock; - if shift_tick_f = '1' then - ser_cb2_o <= shift_reg(7); - end if; end if; + + if falling = '1' then + shift_timer_tick <= timer_b_tick; + end if; + if reset = '1' then shift_clock <= '1'; shift_clock_d <= '1'; - ser_cb2_o <= '1'; end if; end if; end process; - cb1_t <= '0' when shift_clk_sel="11" else serport_en; - cb1_o <= shift_clock_d; - + cb1_t_int <= '0' when shift_clk_sel="11" else serport_en; + cb1_o_int <= shift_clock_d; + ser_cb2_o <= shift_reg(7); + serport_en <= shift_dir or shift_clk_sel(1) or shift_clk_sel(0); - + trigger_serial <= '1' when (ren='1' or wen='1') and addr=x"A" else '0'; + shift_tick_r <= not shift_clock_d and shift_clock; + shift_tick_f <= shift_clock_d and not shift_clock; + process(clock) begin if rising_edge(clock) then if reset = '1' then shift_reg <= X"FF"; - shift_tick_r <= '0'; - shift_tick_f <= '0'; elsif falling = '1' then - shift_tick_r <= not shift_clock_d and shift_clock; - shift_tick_f <= shift_clock_d and not shift_clock; - if wen = '1' and addr = X"A" then shift_reg <= data_in; - elsif shift_tick_r = '1' then - if shift_dir='1' then -- output - shift_reg <= shift_reg(6 downto 0) & shift_reg(7); - else - shift_reg <= shift_reg(6 downto 0) & cb2_c; - end if; + elsif shift_dir='1' and shift_tick_f = '1' then -- output + shift_reg <= shift_reg(6 downto 0) & shift_reg(7); + elsif shift_dir='0' and shift_tick_r = '1' then -- input + shift_reg <= shift_reg(6 downto 0) & cb2_c; end if; end if; end if; end process; -- tell people that we're ready! - serial_event <= shift_tick_r and not shift_active and rising; - + serial_event <= shift_tick_r and not shift_active and rising and serport_en; + process(clock) begin if rising_edge(clock) then if falling = '1' then - if shift_active = '0' then + if shift_active = '0' and shift_mode_control /= "000" then if trigger_serial = '1' then bit_cnt <= 7; shift_active <= '1'; @@ -667,7 +695,7 @@ begin end if; end if; end if; - + if reset='1' then shift_active <= '0'; bit_cnt <= 0;