⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atacntl.vhd

📁 xilinx fpga 下的IDE控制器原代码,贡献一起学习
💻 VHD
📖 第 1 页 / 共 3 页
字号:
  -- compute the next state and outputs 
  -----------------------------------------------------------

  combinatorial : process(state_r, rd, wr, head, cylinder, sector, hDIn, cmd_r, pioDOut,
                          status_r, pioBusy, pioIntrq, wordCnt_r, rtnState_r)
  begin

    -----------------------------------------------------------
    -- setup default values for signals 
    -----------------------------------------------------------

    done       <= NO;
    pioRd      <= NO;
    pioWr      <= NO;
    pioDIn     <= (others => '0');
    pioAddr    <= (others => '0');
    state_x    <= state_r;
    rtnState_x <= rtnState_r;
    cmd_x      <= cmd_r;
    wordCnt_x  <= wordCnt_r;
    status_x   <= status_r;

    if(pioBusy = NO) then

      -----------------------------------------------------------
      -- compute the next state and outputs 
      -----------------------------------------------------------

      case state_r is

        -----------------------------------------------------------------
        -- set and then clear the reset bit in the disk control register
        -----------------------------------------------------------------                               
        when RESET_DRIVE   =>
          pioWr              <= YES;
          pioAddr            <= CONTROL_REG;
          pioDIn(7 downto 0) <= DRIVE_RESET_CMD;
          state_x            <= RESET_DRIVE_1;
          status_x           <= "0000010";
        when RESET_DRIVE_1 =>
          pioWr              <= YES;
          pioAddr            <= CONTROL_REG;
          pioDIn(7 downto 0) <= DRIVE_RELEASE_CMD;
          state_x            <= WAIT_FOR_NOT_BUSY;  -- wait for the drive to go non-busy after reset
          rtnState_x         <= WAIT_FOR_CMD;
          status_x           <= "0000100";

          -----------------------------------------------------------------
          -- abort the current command by issuing a NOP command
          -----------------------------------------------------------------                             
        when ABORT_1 =>
          pioWr              <= YES;
          pioAddr            <= CMD_REG;
          pioDIn(7 downto 0) <= NOP_CMD;
          state_x            <= WAIT_FOR_NOT_BUSY;
          rtnState_x         <= WAIT_FOR_CMD;
          status_x           <= "0000110";

          -----------------------------------------------------------------
          -- wait for the busy bit in the disk status register to clear
          -----------------------------------------------------------------                             
        when WAIT_FOR_NOT_BUSY   =>
          pioRd     <= YES;
          pioAddr   <= STATUS_REG;
          state_x   <= WAIT_FOR_NOT_BUSY_1;
          status_x  <= "0001000";
        when WAIT_FOR_NOT_BUSY_1 =>
          if(pioDOut(STATUS_REG_BSY) = YES) then
            state_x <= WAIT_FOR_NOT_BUSY;  -- busy bit not clear so check it again
          else
            state_x <= rtnState_r;      -- pop the state registers
          end if;
          status_x  <= "0001010";

          -----------------------------------------------------------------
          -- wait for a read or write sector command
          -----------------------------------------------------------------                             
        when WAIT_FOR_CMD =>
          if(rd = YES) then
                                        -- read a sector of the disk
            wordCnt_x  <= SECTOR_SIZE-1;  -- set number of words to read from sector
            cmd_x      <= READ_SECTOR_CMD;  -- command for rading a sector
            state_x    <= SETUP_DRIVE;  -- setup the disk registers for reading the sector
            rtnState_x <= READ_WORDS;
          elsif(wr = YES) then
                                        -- write a sector of the disk
            wordCnt_x  <= SECTOR_SIZE-1;  -- set number of words to write to sector
            cmd_x      <= WRITE_SECTOR_CMD;  -- command for writing a sector
            state_x    <= SETUP_DRIVE;  -- setup the disk registers for writing the sector
            rtnState_x <= WRITE_WORDS;
          else
                                        -- no operation requested
            state_x    <= WAIT_FOR_CMD;  -- keep waiting for a R/W command
          end if;
          status_x     <= "0001100";

          -----------------------------------------------------------------
          -- setup the disk to read or write a sector
          -----------------------------------------------------------------                             
        when SETUP_DRIVE   =>
          -- load the sector count register with the number of sectors to be read/written
          pioWr               <= YES;
          pioAddr             <= SECTOR_CNT_REG;
          pioDIn              <= CONV_STD_LOGIC_VECTOR(SECTORS_PER_RW, pioDIn'length);
          state_x             <= SETUP_DRIVE_1;
          status_x            <= "0001110";
        when SETUP_DRIVE_1 =>
          -- load the number of the sector that will be read/written
          pioWr               <= YES;
          pioAddr             <= SECTOR_REG;
          pioDIn(7 downto 0)  <= sector;
          state_x             <= SETUP_DRIVE_2;
          status_x            <= "0010000";
        when SETUP_DRIVE_2 =>
          -- load the number of the cylinder that contains the desired sector
          pioWr               <= YES;
          pioAddr             <= CYL_LOW_REG;
          pioDIn(7 downto 0)  <= cylinder(7 downto 0);
          state_x             <= SETUP_DRIVE_3;
          status_x            <= "0010010";
        when SETUP_DRIVE_3 =>
          pioWr               <= YES;
          pioAddr             <= CYL_HIGH_REG;
          pioDIn(7 downto 0)  <= cylinder(15 downto 8);
          state_x             <= SETUP_DRIVE_4;
          status_x            <= "0010100";
        when SETUP_DRIVE_4 =>
          -- load the number of the head that accesses the desired cylinder
          pioWr               <= YES;
          pioAddr             <= DRIVE_HEAD_REG;
          pioDIn(7 downto 0)  <= "1010" & head;
          state_x             <= SETUP_DRIVE_5;
          status_x            <= "0010110";
        when SETUP_DRIVE_5 =>
          -- load the command (read sector or write sector)
          pioWr               <= YES;
          pioAddr             <= CMD_REG;
          pioDIn(cmd_r'range) <= cmd_r;
          state_x             <= rtnState_r;
          status_x            <= "0011000";

          -----------------------------------------------------------------
          -- write data to the disk sector
          -----------------------------------------------------------------                             
        when WRITE_WORDS   =>
          state_x                <= WAIT_FOR_NOT_BUSY;
          rtnState_x             <= WRITE_WORDS_1;
          status_x               <= "0011000";
        when WRITE_WORDS_1 =>
          -- check the data request bit to see if the sector is ready for read/write ops
          if(pioDOut(STATUS_REG_DRQ) = YES) then
            state_x              <= WRITE_WORDS_2;  -- if ready, then write sector state
          elsif(pioDOut(STATUS_REG_ERR) = YES) then
            status_x(ERROR_FLAG) <= YES;  -- tell the host there was an error
            state_x              <= error;
          else
                                        -- data not ready, so read status again
            pioRd                <= YES;
            pioAddr              <= STATUS_REG;
            state_x              <= WRITE_WORDS_1;
          end if;
          status_x               <= "0011010";
        when WRITE_WORDS_2 =>
          -- write another word to the disk each time the write control is high
          if(wr = YES) then
            pioWr                <= YES;
            pioAddr              <= DATA_REG;
            pioDIn               <= hDIn;
            state_x              <= WRITE_WORDS_3;
          else
            state_x              <= WRITE_WORDS_2;  -- halt writes to disk when wr is inactive
          end if;
          status_x               <= "0011100";
        when WRITE_WORDS_3 =>
          done                   <= YES;  -- tell the host this word has been written to disk
          if(wordCnt_r = 0) then
            -- this sector is done, so write the next sector
            state_x              <= WRITE_WORDS_4;
          else
            -- otherwise, write the next word to this sector
            wordCnt_x            <= wordCnt_r - 1;
            state_x              <= WRITE_WORDS_2;
          end if;
          status_x               <= "0011110";
        when WRITE_WORDS_4 =>
          -- wait for the interrupt from the disk that indicates the write of the
          -- current sector is done.
          if(pioIntrq = YES) then
                                        -- the interrupt has arrived, so see if there are more sectors to write
            pioRd                <= YES;
            pioAddr              <= STATUS_REG;
            state_x              <= WRITE_WORDS_5;
          else
                                        -- keep waiting for the interrupt
            state_x              <= WRITE_WORDS_4;
          end if;
          status_x               <= "0100000";
        when WRITE_WORDS_5 =>
          if(pioDOut(STATUS_REG_DRQ) = YES) then
                                        -- if the disk is still busy, then there are more sectors to write
            wordCnt_x            <= SECTOR_SIZE-1;  -- set number of words to write to the next sector
            state_x              <= WRITE_WORDS_2;
          else
                                        -- there are no more sectors to write, so go wait for another command
            state_x              <= WAIT_FOR_CMD;
          end if;
          status_x               <= "0100010";

          -----------------------------------------------------------------
          -- read data from the disk sector
          -----------------------------------------------------------------                             
        when READ_WORDS   =>
          if(pioIntrq = YES) then
            pioRd     <= YES;
            pioAddr   <= STATUS_REG;
            state_x   <= READ_WORDS_1;
          else
            state_x   <= READ_WORDS;
          end if;
          status_x    <= "0100100";
        when READ_WORDS_1 =>
          -- read another word from the disk each time the read control is high
          if(rd = YES) then
            pioRd     <= YES;
            pioAddr   <= DATA_REG;
            state_x   <= READ_WORDS_2;
          else
            state_x   <= READ_WORDS_1;  -- halt reads from disk when rd is inactive
          end if;
          status_x    <= "0100110";
        when READ_WORDS_2 =>
          done        <= YES;           -- tell the host a word has been read and is available
          if(wordCnt_r = 0) then
                                        -- this sector is done, so read the next sector
            pioRd     <= YES;
            pioAddr   <= STATUS_REG;
            state_x   <= READ_WORDS_3;
          else
                                        -- otherwise, read the next word from this sector
            wordCnt_x <= wordCnt_r - 1;
            state_x   <= READ_WORDS_1;
          end if;
          status_x    <= "0101000";
        when READ_WORDS_3 =>
          if(pioDOut(STATUS_REG_BSY) = YES) then
                                        -- there are more sectors still to read
            wordCnt_x <= SECTOR_SIZE-1;  -- set number of words to read from the next sector
            state_x   <= READ_WORDS;
          else
                                        -- there are no more sectors to read, so go wait for another command
            state_x   <= WAIT_FOR_CMD;
          end if;
          status_x    <= "0101010";


          -----------------------------------------------------------------
          -- error state.  Requires a reset to leave this state
          -----------------------------------------------------------------                             
        when error =>
          state_x              <= error;
          status_x(ERROR_FLAG) <= YES;

          -----------------------------------------------------------------
          -- unknown state.  Go to the error state
          -----------------------------------------------------------------                             
        when others =>
          state_x              <= error;
          status_x(ERROR_FLAG) <= YES;

      end case;
    end if;
  end process combinatorial;


  -----------------------------------------------------------
  -- update registers on the appropriate clock edge     
  -----------------------------------------------------------

  update : process(rst, clk)
  begin

    if rst = YES then
      -- asynchronous reset
      state_r    <= RESET_DRIVE;        -- upon reset, reset the drive
      rtnState_r <= WAIT_FOR_CMD;       -- and then wait for read/write commands
      cmd_r      <= (others => '0');
      wordCnt_r  <= 0;
      status_r   <= (others => '0');    -- clear the status register
    elsif rising_edge(clk) then
      if(abort = YES) then
        -- abort a read or write sector command and go back to wait for another command
        state_r  <= ABORT_1;
      else
        state_r  <= state_x;
      end if;
      rtnState_r <= rtnState_x;
      cmd_r      <= cmd_x;
      wordCnt_r  <= wordCnt_x;
      status_r   <= status_x;
    end if;

  end process update;

end arch;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -