Skip to content

Instantly share code, notes, and snippets.

@epall
Created February 10, 2010 03:37
Show Gist options
  • Save epall/299997 to your computer and use it in GitHub Desktop.
Save epall/299997 to your computer and use it in GitHub Desktop.
require 'Computer.Build'
controller = state_machine "ide_controller" do |m|
m.input :reset, VHDL::STD_LOGIC
m.input :instr_command, VHDL::STD_LOGIC_VECTOR(7..0)
m.input :instr_address, VHDL::STD_LOGIC_VECTOR(7..0)
m.input :instr_data, VHDL::STD_LOGIC_VECTOR(15..0)
m.output :result_command, VHDL::STD_LOGIC_VECTOR(7..0)
m.output :result_status, VHDL::STD_LOGIC_VECTOR(7..0)
m.output :result_data, VHDL::STD_LOGIC_VECTOR(15..0)
m.input :available_instr, VHDL::STD_LOGIC
m.output :read_instr, VHDL::STD_LOGIC
m.output :write_result, VHDL::STD_LOGIC
m.output :ide_reset_n, VHDL::STD_LOGIC
m.input :ide_data_in, VHDL::STD_LOGIC_VECTOR(15..0)
m.output :ide_data_out, VHDL::STD_LOGIC_VECTOR(15..0)
m.output :ide_data_write_n, VHDL::STD_LOGIC
m.output :ide_data_read_n, VHDL::STD_LOGIC
m.output :ide_address, VHDL::STD_LOGIC_VECTOR(2..0)
m.output :ide_cs_1f0_n, VHDL::STD_LOGIC
m.output :ide_cs_3f0_n, VHDL::STD_LOGIC
m.input :ide_ready, VHDL::STD_LOGIC
m.input :ide_int_request, VHDL::STD_LOGIC
m.input :ide_16_bit_n, VHDL::STD_LOGIC
m.input :ide_dasp_n, VHDL::STD_LOGIC
m.output :ide_data_OE, VHDL::STD_LOGIC
m.signal :command_buffer, VHDL::STD_LOGIC_VECTOR(7..0)
m.signal :address_buffer, VHDL::STD_LOGIC_VECTOR(7..0)
m.signal :data_buffer, VHDL::STD_LOGIC_VECTOR(15..0)
m.reset do |r|
r.goto :wait
r.low :ide_reset_n
r.high :ide_data_write_n
r.high :ide_data_read_n
r.assign :ide_address, '000'
r.high :ide_cs_1f0_n
r.high :ide_cs_3f0_n
r.assign :ide_data_out, '0000000000000000'
r.assign :result_command, "00000000"
r.assign :result_status, "00000000"
r.assign :result_data, "0000000000000000"
r.low :read_instr
r.low :write_result
end
m.state :wait do |s|
s.high :ide_reset_n
s.low :write_result
s.assign :read_instr, :available_instr
end
m.transition :from => :wait, :to => :decode, :on => equal(:available_instr, '1')
m.state :decode do |s|
s.assign :command_buffer, :instr_command
s.assign :address_buffer, :instr_address
s.assign :data_buffer, :instr_data
s.low :read_instr
s.case(:instr_command) do |c|
c["00000000"] = block do |b|
b.assign :result_command, :instr_command
b.assign :result_status, "00000000"
b.assign :result_data, "0000000000000000"
end
c["00000011"] = block do |b|
b.assign :result_command, :instr_command
b.assign :ide_address, 0, :instr_address, 0
b.assign :ide_address, 1, :instr_address, 1
b.assign :ide_address, 2, :instr_address, 2
end
c["00000010"] = block do |b|
b.assign :result_command, :instr_command
b.assign :ide_address, 0, :instr_address, 0
b.assign :ide_address, 1, :instr_address, 1
b.assign :ide_address, 2, :instr_address, 2
b.low :ide_cs_1f0_n
end
end
end
m.transition :from => :decode, :to => :writestatus,
:on => equal(:instr_command, "00000000")
m.transition :from => :decode, :to => :data_on_bus,
:on => equal(:instr_command, "00000011")
m.transition :from => :decode, :to => :data_on_bus,
:on => equal(:instr_command, "00000010")
m.state :writestatus do |s|
s.high :write_result
s.high :ide_cs_1f0_n
s.high :ide_data_read_n
end
m.transition :from => :writestatus, :to => :wait
m.state :action do |s|
ifelse = s.if equal(:instr_command, "00000011") do |b|
b.assign :result_data, :ide_data_in
end
ifelse.else do |b|
b.assign :result_data, "0000000000000000"
end
s.low :ide_data_OE
end
m.transition :from => :action, :to => :writestatus
m.state :data_on_bus do |s|
s.if equal(:command_buffer, "00000011") do |b|
b.high :ide_data_write_n
b.low :ide_data_read_n
end
end
m.transition :from => :data_on_bus, :to => :action,
:condition => equal(:command_buffer, "00000011")
end
generate_vhdl controller
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY ide_controller IS
PORT(
clock: in std_logic;
ide_16_bit_n: in STD_LOGIC;
ide_dasp_n: in STD_LOGIC;
instr_command: in STD_LOGIC_VECTOR(7 downto 0);
ide_data_in: in STD_LOGIC_VECTOR(15 downto 0);
instr_address: in STD_LOGIC_VECTOR(7 downto 0);
ide_ready: in STD_LOGIC;
available_instr: in STD_LOGIC;
reset: in STD_LOGIC;
instr_data: in STD_LOGIC_VECTOR(15 downto 0);
ide_int_request: in STD_LOGIC;
ide_data_read_n: out STD_LOGIC;
write_result: out STD_LOGIC;
ide_address: out STD_LOGIC_VECTOR(2 downto 0);
result_command: out STD_LOGIC_VECTOR(7 downto 0);
ide_reset_n: out STD_LOGIC;
ide_cs_1f0_n: out STD_LOGIC;
result_status: out STD_LOGIC_VECTOR(7 downto 0);
ide_data_OE: out STD_LOGIC;
ide_cs_3f0_n: out STD_LOGIC;
result_data: out STD_LOGIC_VECTOR(15 downto 0);
ide_data_out: out STD_LOGIC_VECTOR(15 downto 0);
ide_data_write_n: out STD_LOGIC;
read_instr: out STD_LOGIC
);
END ide_controller;
ARCHITECTURE arch_ide_controller OF ide_controller IS
TYPE STATE_TYPE IS ( state_wait, state_decode, state_writestatus, state_action, state_data_on_bus );
SIGNAL state : STATE_TYPE;
SIGNAL command_buffer : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL address_buffer : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL data_buffer : STD_LOGIC_VECTOR(15 downto 0);
BEGIN
PROCESS(clock)
BEGIN
IF reset = '1' THEN
state <= state_wait;
ide_reset_n <= '0';
ide_data_write_n <= '1';
ide_data_read_n <= '1';
ide_address <= "000";
ide_cs_1f0_n <= '1';
ide_cs_3f0_n <= '1';
ide_data_out <= "0000000000000000";
result_command <= "00000000";
result_status <= "00000000";
result_data <= "0000000000000000";
read_instr <= '0';
write_result <= '0';
ELSIF clock'EVENT and clock = '1' THEN
CASE state IS
WHEN state_writestatus =>
write_result <= '1';
ide_cs_1f0_n <= '1';
ide_data_read_n <= '1';
WHEN state_wait =>
ide_reset_n <= '1';
write_result <= '0';
read_instr <= available_instr;
WHEN state_action =>
IF instr_command = "00000011" THEN
result_data <= ide_data_in;
ELSE
result_data <= "0000000000000000";
END IF;
ide_data_OE <= '0';
WHEN state_decode =>
command_buffer <= instr_command;
address_buffer <= instr_address;
data_buffer <= instr_data;
read_instr <= '0';
CASE instr_command IS
WHEN "00000010" =>
result_command <= instr_command;
ide_address(0) <= instr_address(0);
ide_address(1) <= instr_address(1);
ide_address(2) <= instr_address(2);
ide_cs_1f0_n <= '0';
WHEN "00000011" =>
result_command <= instr_command;
ide_address(0) <= instr_address(0);
ide_address(1) <= instr_address(1);
ide_address(2) <= instr_address(2);
WHEN "00000000" =>
result_command <= instr_command;
result_status <= "00000000";
result_data <= "0000000000000000";
END CASE;
WHEN state_data_on_bus =>
IF command_buffer = "00000011" THEN
ide_data_write_n <= '1';
ide_data_read_n <= '0';
END IF;
END CASE;
END IF;
IF state = state_wait and available_instr = '1' THEN
state <= state_decode;
END IF;
IF state = state_decode and instr_command = "00000000" THEN
state <= state_writestatus;
END IF;
IF state = state_decode and instr_command = "00000011" THEN
state <= state_data_on_bus;
END IF;
IF state = state_decode and instr_command = "00000010" THEN
state <= state_data_on_bus;
END IF;
IF state = state_writestatus THEN
state <= state_wait;
END IF;
IF state = state_action THEN
state <= state_writestatus;
END IF;
IF state = state_data_on_bus and command_buffer = "00000011" THEN
state <= state_action;
END IF;
END PROCESS;
END arch_ide_controller;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment