Hello,
to improve compatibility I put in place a floppy rotation emulation.
My floppy module is VHDL not Verilog.
Here is the code snippet for the rotation :
internal signals:
Code:
-- Disk rotation
TYPE REV_STATE_TYPE IS
(
REV_STATE_IDLE,
REV_STATE_HDR,
REV_STATE_DATA,
REV_STATE_GAP
);
SIGNAL rev_state : REV_STATE_TYPE;
SIGNAL rev_idle : STD_LOGIC;
SIGNAL rev_hdr : STD_LOGIC;
SIGNAL rev_data : STD_LOGIC;
SIGNAL rev_gap : STD_LOGIC;
SIGNAL rev_clk_ctr : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL rev_word_ctr : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL rev_word_gap : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL rev_sect_ctr : STD_LOGIC_VECTOR(3 DOWNTO 0);
process:
Code:
-------------------
-- Disk rotation --
-------------------
-- PAL clock : 7.093750 MHz
-- NTSC clock : 7.159091 MHz
-- 224 clocks per 32-bit MFM word
-- 3167 (PAL) or 3196 (NTSC) 32-bit MFM words per track
-- 272 32-bit MFM words per sector (header:16, data:256)
-- End of track gap : 175 (PAL) or 204 (NTSC) 32-bit MFM words
PROCESS
(
reset, -- Reset signal
clk, -- Bus clock
dsk_sel_n, -- Disk drive select
dsk_sel_dly, -- Disk drive select delayed
dsk_mtr_n, -- Disk spinning motor
drv_mtr, -- Latched disk spinning state
drv_ena, -- Drive enabled
rev_state, -- Disk rotation state
rev_clk_ctr, -- Clock counter
rev_word_ctr, -- Long word counter
rev_word_gap, -- Number of long words in a track gap
rev_sect_ctr -- Sector counter
)
BEGIN
IF (reset = '1') THEN
dsk_sel_dly <= "1111";
drv_mtr <= "0000";
rev_clk_ctr <= X"00";
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_IDLE;
ELSIF (rising_edge(clk)) THEN
-- Drives motors latches
dsk_sel_dly <= dsk_sel_n;
FOR i IN 0 TO 3 LOOP
IF (dsk_sel_n(i) = '0') AND (dsk_sel_dly(i) = '1') THEN
drv_mtr(i) <= (NOT dsk_mtr_n) AND drv_ena(i);
END IF;
END LOOP;
-- Disk rotation state machine
IF (rev_clk_ctr = X"DF") THEN
CASE rev_state IS
-- Spinning motor OFF
WHEN REV_STATE_IDLE =>
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
-- Spinning motor ON
IF (drv_mtr /= "0000") THEN
rev_state <= REV_STATE_HDR;
END IF;
-- Sector header
WHEN REV_STATE_HDR =>
IF (drv_mtr = "0000") THEN
-- Spinning motor OFF
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_IDLE;
ELSE
IF (rev_word_ctr = X"0F") THEN
-- Sector data after 16 long words
rev_word_ctr <= X"00";
rev_state <= REV_STATE_DATA;
ELSE
rev_word_ctr <= rev_word_ctr + '1';
END IF;
END IF;
-- Sector data
WHEN REV_STATE_DATA =>
IF (drv_mtr = "0000") THEN
-- Spinning motor OFF
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_IDLE;
ELSE
rev_word_ctr <= rev_word_ctr + '1';
IF (rev_word_ctr = X"FF") THEN
IF (rev_sect_ctr = X"A") THEN
-- Track gap after 256 long words and sector #10
rev_sect_ctr <= X"F";
rev_state <= REV_STATE_GAP;
ELSE
-- Next sector header after 256 long words
rev_sect_ctr <= rev_sect_ctr + '1';
rev_state <= REV_STATE_HDR;
END IF;
END IF;
END IF;
-- Track gap
WHEN REV_STATE_GAP =>
IF (drv_mtr = "0000") THEN
-- Spinning motor OFF
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_IDLE;
ELSE
IF (rev_word_ctr = rev_word_gap) THEN
-- Sector #0 header after track gap
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_HDR;
ELSE
rev_word_ctr <= rev_word_ctr + '1';
END IF;
END IF;
WHEN OTHERS =>
rev_clk_ctr <= X"00";
rev_word_ctr <= X"00";
rev_sect_ctr <= X"0";
rev_state <= REV_STATE_IDLE;
END CASE;
rev_clk_ctr <= X"00";
ELSE
rev_clk_ctr <= rev_clk_ctr + '1';
END IF;
END IF;
END PROCESS;
-- Disk LED is ON if at least one motor is ON
dsk_led <= '1' WHEN (drv_mtr /= "0000") ELSE '0';
-- Disk index is ON at the end of the track gap (1.5 ms duration)
dsk_idx <= (rev_word_ctr(7) AND rev_gap);
"rev_word_gap" has to be set to 174 or 203 depending if you use a PAL (28.375160 MHz) or NTSC (28.636363 MHz) clock.
maybe, somebody can port it back to the original Minimig code. Yaqube, maybe ?
Regards,
Frederic