snippet.host

minimal text and code snippet hosting

welcome, guest. why not login or register?

disk_ctrl.vhd

created: views: 447 size: 3.64 KiB lines: 103 clone raw download
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;