Car Selector VHDL Code
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
PACKAGE types IS
CONSTANT max_car: std_logic_vector:= "0110";
CONSTANT busy_status: std_logic_vector:= "1001";
CONSTANT ADDR_WIDTH: integer:= 4;
CONSTANT DATA_WIDTH: integer:= 12;
SUBTYPE saddr IS std_logic_vector(3 DOWNTO 0);
SUBTYPE laddr IS std_logic_vector(11 DOWNTO 0);
SUBTYPE maddr IS std_logic_vector(5 DOWNTO 0);
SUBTYPE lbit IS std_logic_vector(1 DOWNTO 0);
subtype memaddr IS std_logic_vector(7 DOWNTO 0);
TYPE state_type IS (initialize, get_mm_addr, get_mm_data,
compare_mm_data,
change_mm_addr, write_stop, read_data,
compare_data, check_distance,
change_addr, check_done, write_data);
END types;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE work.types.ALL;
LIBRARY lpm;
USE lpm.lpm_components.ALL;
ENTITY car_sel IS
PORT(
clock, internal, up, reg_ready, mem_ready
: IN std_logic;
slow_clock
:
IN std_logic;
floor_req
:
IN maddr;
car_id
:
IN saddr;
reg_out
:
IN laddr;
mem_out
:
IN memaddr;
kick_off
:
IN std_logic;
reg_addr, car_to_move
:
OUT saddr;
reg_in
:
OUT laddr;
reg_we, reg_request, mem_we, mem_request
: OUT std_logic;
mem_in
:
OUT memaddr;
request_location
:
OUT maddr;
current_location
:
OUT std_logic_vector(7 DOWNTO 0);
ready
:
OUT std_logic;
path
:
OUT std_logic;
mem_addr
:
OUT memaddr
);
END ENTITY;
ARCHITECTURE behaviour OF car_sel IS
SIGNAL state, next_state
:
state_type;
SIGNAL car_data, mem_reg, data_reg
:
laddr;
SIGNAL car_local, difference, dist
:
maddr;
SIGNAL request_latch, tmp_location
:
maddr;
SIGNAL car_addr, car_addr_latch, reg_status
: saddr;
SIGNAL car_status, move_car
:
saddr;
SIGNAL found
:
std_logic;
SIGNAL done, calc_dist
:
std_logic;
SIGNAL done_latch
:
std_logic;
SIGNAL internal_latch, done_shaft
:
std_logic;
SIGNAL found_path : std_logic;
SIGNAL shaft, shafted
:
lbit;
SIGNAL mm_addr
:
memaddr;
SIGNAL mm_data
:
memaddr;
------------------------------------------------------------------------------
BEGIN
car_select: PROCESS (slow_clock) IS
BEGIN
WAIT UNTIL rising_edge(slow_clock);
CASE state IS
WHEN initialize =>
reg_request <= '0';
found_path <= '0';
reg_we <= '0';
ready <= '0';
done_shaft <= '0';
IF internal = '1' THEN
move_car <= car_id;
car_addr_latch <=
car_id;
ELSE
car_addr_latch <=
"0001";
END IF;
difference <= "111111";
shaft <= "00";
done_latch <= '0';
next_state <= get_mm_addr;
WHEN get_mm_addr =>
mem_request <= '1';
mem_addr <= shaft & floor_req;
mem_we <= '0';
IF mem_ready = '1' THEN
next_state <=
get_mm_data;
ELSE
next_state <=
get_mm_addr;
END IF;
WHEN get_mm_data =>
mm_data <= mem_out;
next_state <= compare_mm_data;
WHEN compare_mm_data =>
IF (mm_data(3) = '1' AND mm_data(2) = '0' AND
mm_data(1) = up) THEN
move_car <=
mm_data(7 DOWNTO 4);
mem_addr <=
mm_data(7 DOWNTO 4);
next_state <=
write_stop;
ELSIF (done_shaft = '1') THEN
reg_addr <=
car_addr_latch;
reg_request <= '1';
next_state <=
read_data;
ELSE
next_state <=
change_mm_addr;
END IF;
WHEN change_mm_addr =>
IF (shaft + 1) = "11" THEN
done_shaft <= '1';
END IF;
shaft <= shaft + 1;
next_state <= get_mm_addr;
WHEN write_stop =>
mem_we <= '1';
mem_in <= mm_data(7 DOWNTO 1) & '1';
mem_request <= '0';
car_addr_latch <= move_car;
found_path <= '1';
reg_addr <= car_addr_latch;
reg_request <= '1';
next_state <= read_data;
WHEN read_data =>
IF reg_ready = '0' THEN
mem_request <= '0';
reg_request <= '1';
mem_reg <= reg_out;
car_status <=
reg_out(11 DOWNTO 8);
car_local <=
reg_out(5 DOWNTO 0);
shafted <= reg_out(7
DOWNTO 6);
next_state <=
compare_data;
ELSE
next_state <=
read_data;
END IF;
WHEN compare_data =>
IF internal = '1' or found_path = '1' THEN
tmp_location <=
car_local;
done_latch <= '1';
found <= '1';
next_state <=
write_data;
ELSIF (car_status = "0000") THEN
found <= '1';
car_status(3) <=
'1';
car_status(1) <= up;
calc_dist <= '1';
IF (request_latch >
car_local) THEN
dist
<= (request_latch - car_local);
ELSE
dist
<= (car_local - request_latch);
END IF;
next_state <=
check_distance;
ELSIF (car_status /= "0000") THEN
found <= '0';
car_status <=
reg_out(11 DOWNTO 8);
next_state <=
change_addr;
END IF;
WHEN check_distance =>
IF((dist < difference) AND calc_dist = '1')
THEN
difference <= dist;
move_car <=
car_addr;
data_reg <= reg_out;
tmp_location <=
car_local;
END IF;
next_state <= change_addr;
WHEN change_addr =>
IF ((car_addr_latch + 1) > max_car) THEN
car_addr_latch <=
"0001";
ELSE
car_addr_latch <=
car_addr_latch + 1;
END IF;
next_state <= check_done;
WHEN check_done =>
IF(calc_dist = '1' AND move_car /=
"0000" AND car_addr = max_car) THEN
done_latch <= '1';
next_state <=
write_data;
ELSE
next_state <=
read_data;
END IF;
WHEN write_data =>
IF found = '1' THEN
car_to_move <=
move_car;
reg_we <= found;
reg_in <= car_status
& data_reg(7 DOWNTO 0);
request_location <=
request_latch;
current_location <=
shafted & tmp_location;
path <= found_path;
ready <= '1';
reg_request <= '0';
ELSIF found = '0' THEN
next_state <=
initialize;
END IF;
END CASE;
END PROCESS car_select;
latch: PROCESS(clock) IS
BEGIN
WAIT UNTIL rising_edge(clock);
done <= done_latch;
END PROCESS latch;
input_latch: PROCESS(clock, internal) IS
BEGIN
WAIT UNTIL rising_edge(clock);
request_latch <= floor_req;
END PROCESS input_latch;
addr_latch: PROCESS(clock, car_addr_latch) IS
BEGIN
WAIT UNTIL rising_edge(clock);
car_addr <= car_addr_latch;
END PROCESS addr_latch;
state_register: PROCESS(clock, kick_off)
BEGIN
IF kick_off = '1' THEN
state <= initialize;
ELSIF rising_edge(clock) THEN
state <= next_state;
END IF;
END PROCESS state_register;
END behaviour;