disk_ctrl.vhd
library IEEE; |
|
use IEEE.STD_LOGIC_1164.ALL; |
|
use IEEE.numeric_std.all; |
|
use work.types.all; |
|
use work.disk.all; |
|
entity disk_ctrl is |
|
port ( clk : in std_logic; |
|
addr : inout byte; |
|
data : inout byte; |
|
DMA_req : out std_logic; |
|
DMA_ack : in std_logic |
|
); |
|
end disk_ctrl; |
|
architecture Behavioral of disk_ctrl is |
|
constant param_1 : byte := x"FB"; |
|
constant param_2 : byte := x"FC"; |
|
constant param_3 : byte := x"FD"; |
|
constant param_4 : byte := x"FE"; |
|
constant read_cmnd : byte := x"FF"; |
|
constant sector_size : integer := 256; |
|
signal buff : disk_block; |
|
signal b_addr : byte; |
|
signal b_count : byte; |
|
signal b_offset : byte; |
|
signal b_length : byte; |
|
begin |
|
process (clk) |
|
type rd_state is ( idle, |
|
buff_sect, |
|
wait_DMA, |
|
transfer_byte, |
|
inc_byte_counter |
|
); |
|
variable state : rd_state := idle; |
|
variable block_counter : integer := 0; |
|
variable byte_counter : integer := 0; |
|
variable block_size : integer := sector_size; |
|
begin |
|
if rising_edge (clk) then |
|
if addr = param_1 then |
|
b_addr <= data; |
|
end if; |
|
if addr = param_2 then |
|
b_count <= data; |
|
end if; |
|
if addr = param_3 then |
|
b_offset <= data; |
|
end if; |
|
if addr = param_4 then |
|
b_length <= data; |
|
end if; |
|
if addr = read_cmnd then |
|
byte_counter := to_integer(unsigned(b_offset)); |
|
block_counter := 0; |
|
state := buff_sect; |
|
end if; |
|
case state is |
|
when idle => |
|
when buff_sect => |
|
buff <= disk_data(to_integer(unsigned(b_addr))+block_counter); |
|
if block_counter = to_integer(unsigned(b_count)) then |
|
if to_integer(unsigned(b_length)) /= 0 then |
|
block_size := to_integer(unsigned(b_length)); |
|
end if; |
|
end if; |
|
DMA_req <= '1'; |
|
state := wait_DMA; |
|
when wait_DMA => |
|
if DMA_ack = '1' then |
|
state := transfer_byte; |
|
end if; |
|
when transfer_byte => |
|
if byte_counter < block_size then |
|
data <= buff(byte_counter); |
|
state := inc_byte_counter; |
|
else |
|
DMA_req <= '0'; |
|
if block_counter < to_integer(unsigned(b_count)) then |
|
block_counter := block_counter + 1; |
|
byte_counter := 0; |
|
state := buff_sect; |
|
else |
|
addr <= (others => 'Z'); |
|
data <= (others => 'Z'); |
|
block_size := sector_size; |
|
state := idle; |
|
end if; |
|
end if; |
|
when inc_byte_counter => |
|
byte_counter := byte_counter + 1; |
|
state := transfer_byte; |
|
end case; |
|
end if; |
|
end process; |
|
end Behavioral; |