mirror of
https://github.com/MiSTer-devel/MultiComp_MiSTer.git
synced 2026-04-19 03:04:38 +00:00
increase read buffer of UART from 16 to 64 bytes allow selection of UART baud rate allow selection of sd controller or image controller update readme.md with more explanation of above and more detail on MultiComp use specifically for CP/M
141 lines
4.8 KiB
VHDL
141 lines
4.8 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
entity image_controller is
|
|
port (
|
|
-- System interface
|
|
clk : in std_logic;
|
|
n_reset : in std_logic;
|
|
|
|
-- CPU interface
|
|
n_rd : in std_logic;
|
|
n_wr : in std_logic;
|
|
dataIn : in std_logic_vector(7 downto 0);
|
|
dataOut : out std_logic_vector(7 downto 0);
|
|
regAddr : in std_logic_vector(2 downto 0);
|
|
|
|
-- Status output
|
|
driveLED : out std_logic := '1'
|
|
);
|
|
end image_controller;
|
|
|
|
architecture rtl of image_controller is
|
|
-- Status register bits
|
|
constant STATUS_WRITE_READY : integer := 7;
|
|
constant STATUS_READ_READY : integer := 6;
|
|
constant STATUS_BUSY : integer := 5;
|
|
|
|
-- Internal registers
|
|
signal status : std_logic_vector(7 downto 0);
|
|
signal block_busy : std_logic := '0';
|
|
signal address : std_logic_vector(31 downto 0) := (others => '0');
|
|
|
|
-- Data buffering
|
|
signal read_data : std_logic_vector(7 downto 0);
|
|
signal write_data : std_logic_vector(7 downto 0);
|
|
signal buffer_addr : unsigned(8 downto 0); -- 0-511 bytes per sector
|
|
|
|
-- Transfer state machine
|
|
type transfer_state is (IDLE, READ_SECTOR, WRITE_SECTOR, WAIT_COMPLETE);
|
|
signal state : transfer_state := IDLE;
|
|
|
|
-- Activity LED timer
|
|
signal led_counter : integer range 0 to 1000000 := 0;
|
|
|
|
begin
|
|
-- Address register handling
|
|
process(n_wr)
|
|
begin
|
|
if rising_edge(n_wr) then
|
|
case regAddr is
|
|
when "010" => address(7 downto 0) <= dataIn;
|
|
when "011" => address(15 downto 8) <= dataIn;
|
|
when "100" => address(23 downto 16) <= dataIn;
|
|
when others => null;
|
|
end case;
|
|
end if;
|
|
end process;
|
|
|
|
-- Command and status handling
|
|
process(clk, n_reset)
|
|
begin
|
|
if n_reset = '0' then
|
|
state <= IDLE;
|
|
block_busy <= '0';
|
|
buffer_addr <= (others => '0');
|
|
led_counter <= 0;
|
|
status <= x"80"; -- Ready to write
|
|
|
|
elsif rising_edge(clk) then
|
|
-- Default LED timeout behavior
|
|
if led_counter /= 0 then
|
|
led_counter <= led_counter - 1;
|
|
end if;
|
|
|
|
-- Update status register
|
|
if state = IDLE then
|
|
status(STATUS_WRITE_READY) <= '1';
|
|
status(STATUS_READ_READY) <= '0';
|
|
elsif state = READ_SECTOR then
|
|
status(STATUS_WRITE_READY) <= '0';
|
|
status(STATUS_READ_READY) <= '1';
|
|
else
|
|
status(STATUS_WRITE_READY) <= '0';
|
|
status(STATUS_READ_READY) <= '0';
|
|
end if;
|
|
status(STATUS_BUSY) <= block_busy;
|
|
|
|
case state is
|
|
when IDLE =>
|
|
if n_wr = '0' and regAddr = "001" then
|
|
case dataIn is
|
|
when x"00" => -- Read command
|
|
state <= READ_SECTOR;
|
|
block_busy <= '1';
|
|
buffer_addr <= (others => '0');
|
|
led_counter <= 1000000; -- 1M cycles = 20ms at 50MHz
|
|
|
|
when x"01" => -- Write command
|
|
state <= WRITE_SECTOR;
|
|
block_busy <= '1';
|
|
buffer_addr <= (others => '0');
|
|
led_counter <= 1000000;
|
|
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
|
|
when READ_SECTOR =>
|
|
if buffer_addr = 511 then
|
|
state <= IDLE;
|
|
block_busy <= '0';
|
|
elsif n_rd = '0' and regAddr = "000" then
|
|
buffer_addr <= buffer_addr + 1;
|
|
end if;
|
|
|
|
when WRITE_SECTOR =>
|
|
if buffer_addr = 511 then
|
|
state <= IDLE;
|
|
block_busy <= '0';
|
|
elsif n_wr = '0' and regAddr = "000" then
|
|
write_data <= dataIn;
|
|
buffer_addr <= buffer_addr + 1;
|
|
end if;
|
|
|
|
when others =>
|
|
state <= IDLE;
|
|
end case;
|
|
end if;
|
|
end process;
|
|
|
|
-- Data output multiplexing
|
|
dataOut <= status when regAddr = "001" else
|
|
read_data when regAddr = "000" else
|
|
x"FF";
|
|
|
|
-- Drive LED control
|
|
driveLED <= '0' when led_counter /= 0 else '1';
|
|
|
|
end rtl; |