altera/MainController/RAM9X8_ParallelBusMaster.vhd

269 lines
9.2 KiB
VHDL
Raw Normal View History

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity RAM9X8_ParallelBusMaster is
generic(
PB_BASE_ADDRESS : integer := 6;
ARRAY_LENGTH : integer := 256;
DATA_BUS_WIDTH : integer := 8;
ADDRESS_BUS_WIDTH : integer := 9
);
port(
clk : in std_logic;
data : inout std_logic_vector(DATA_BUS_WIDTH - 1 downto 0);
address : in std_logic_vector(ADDRESS_BUS_WIDTH - 1 downto 0);
we : in std_logic;
oe : in std_logic;
ce : in std_logic;
pbclk : out std_logic := '1';
pbce : out std_logic := '1';
pbdir : out std_logic_vector(1 downto 0) := (others => '1');
pbdata : inout std_logic_vector(15 downto 0) := (others => 'Z');
pback : in std_logic
);
end entity;
architecture behavorial of RAM9X8_ParallelBusMaster is
signal PB_FIRST_FREE_LOWER : integer := PB_BASE_ADDRESS;
signal PB_FIRST_FREE_UPPER : integer := PB_BASE_ADDRESS + 1;
signal PB_CMD_LOWER : integer := PB_BASE_ADDRESS + 2;
signal PB_CMD_UPPER : integer := PB_BASE_ADDRESS + 3;
signal PB_FILL_ADDRESS_SPACE_LOWER : integer := PB_BASE_ADDRESS + 4;
signal PB_FILL_ADDRESS_SPACE_UPPER : integer := PB_BASE_ADDRESS + 5;
signal PB_CONTROL_2_LOWER : integer := PB_BASE_ADDRESS + 6;
signal PB_CONTROL_2_UPPER : integer := PB_BASE_ADDRESS + 7;
signal PB_CONTROL_1_LOWER : integer := PB_BASE_ADDRESS + 8;
signal PB_CONTROL_1_UPPER : integer := PB_BASE_ADDRESS + 9;
type mem is array (ARRAY_LENGTH - 1 downto 0) of std_logic_vector(7 downto 0);
signal memoryAddress : mem;
signal memoryData : mem;
signal firstFreeBuf : std_logic_vector(15 downto 0) := (others => '0');
signal cmdBuf : std_logic_vector(15 downto 0) := (others => '0');
signal fasBuf : std_logic_vector(15 downto 0) := (others => '0');
signal controlBuf : std_logic_vector(7 downto 0) := (others => '0');
signal errorBuf : std_logic_vector(7 downto 0) := x"00";
signal addrTemp : std_logic_vector(7 downto 0) := x"00";
signal dataTemp : std_logic_vector(15 downto 0) := x"0000";
signal circleCounterBuf : std_logic_vector(7 downto 0) := x"00";
type CommunicationState_start is (Waiting, TransmiteAddress, TransmiteCheck, PreparingToReceiveData, ReceiveData, ReceiveCheck, Timeout, ReceiveCheckTimeout);
signal CommunicationState : CommunicationState_start := Waiting ;
signal lineBusy : std_logic := '1';
signal start : std_logic := '0';
signal startPrev : std_logic := '0';
begin
process (we, oe, ce)
variable addr : integer range 0 to 2**ADDRESS_BUS_WIDTH - 1 := 0;
variable position : integer range 0 to ARRAY_LENGTH - 1 := 0;
begin
if (ce = '0') then -- Если микросхема выбрана
addr := conv_integer(address);
if (addr = PB_FIRST_FREE_UPPER or addr = PB_FIRST_FREE_LOWER or addr = PB_CMD_UPPER or addr = PB_CMD_LOWER
or addr = PB_FILL_ADDRESS_SPACE_UPPER or addr = PB_FILL_ADDRESS_SPACE_LOWER or addr = PB_CONTROL_2_UPPER or addr = PB_CONTROL_2_LOWER
or addr = PB_CONTROL_1_UPPER or addr = PB_CONTROL_1_LOWER) then
if (oe = '0' and we = '1') then -- Если сигнал чтения активен, а записи нет
case addr is
when PB_FIRST_FREE_UPPER =>
data <= firstFreeBuf(15 downto 8);
when PB_FIRST_FREE_LOWER =>
data <= firstFreeBuf(7 downto 0);
when PB_CMD_UPPER =>
data <= cmdBuf(15 downto 8);
when PB_CMD_LOWER =>
data <= cmdBuf(7 downto 0);
when PB_FILL_ADDRESS_SPACE_UPPER =>
data <= fasBuf(15 downto 8);
when PB_FILL_ADDRESS_SPACE_LOWER =>
data <= fasBuf(7 downto 0);
when PB_CONTROL_2_UPPER =>
data <= (others => '0');
when PB_CONTROL_2_LOWER =>
data <= circleCounterBuf;
when PB_CONTROL_1_UPPER =>
data <= errorBuf;
when PB_CONTROL_1_LOWER =>
data <= controlBuf(7 downto 0);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
elsif (oe = '1' and we = '0') then -- Если сигнал записи активен, а чтения нет
case addr is
when PB_FIRST_FREE_UPPER =>
firstFreeBuf(15 downto 8) <= data;
when PB_FIRST_FREE_LOWER =>
firstFreeBuf(7 downto 0) <= data;
when PB_CMD_UPPER =>
cmdBuf(15 downto 8) <= data;
when PB_CMD_LOWER =>
cmdBuf(7 downto 0) <= data;
when PB_FILL_ADDRESS_SPACE_UPPER =>
fasBuf(15 downto 8) <= data;
when PB_FILL_ADDRESS_SPACE_LOWER =>
fasBuf(7 downto 0) <= data;
position := conv_integer(data);
memoryAddress(position) <= fasBuf(15 downto 8);
when others =>
data <= (others => 'Z'); -- Запретить запись на шину
end case;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
elsif (addr >= conv_integer(firstFreeBuf) and addr <= conv_integer(firstFreeBuf) + conv_integer(cmdBuf(7 downto 0))) then
if (oe = '0') then -- Если сигнал чтения активен
data <= memoryData(addr - conv_integer(firstFreeBuf));
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
else
data <= (others => 'Z'); -- Запретить запись на шину
end if;
end process;
process(clk) is
variable count : integer range 0 to 255 := 0;
variable countValue : integer range 0 to 255 := 63;
variable errorCount : integer range 0 to 15 := 0;
variable position : integer range 0 to ARRAY_LENGTH - 1 := 0;
variable circleCounter : integer range 0 to 255 := 0;
begin
if(rising_edge (clk)) then
if cmdBuf(15) = '1' then
case CommunicationState is
when Waiting =>
if errorCount < conv_integer(cmdBuf(11 downto 8)) then
addrTemp <= memoryAddress(position);
CommunicationState <= TransmiteAddress;
else
errorBuf(7 downto 4) <= conv_std_logic_vector(errorCount, 4);
end if;
pbclk <= '1';
pbce <= '1';
pbdata <= (others =>'Z');
pbdir <= b"11";
countValue := 7;
count := 0;
circleCounterBuf <= conv_std_logic_vector(circleCounter, 8);
when TransmiteAddress =>
if count < countValue then
if count = 0 then
pbdata(15 downto 8) <= addrTemp;
pbdata(7 downto 0) <= not addrTemp;
end if;
count := count + 1;
else
pbce <= '0';
CommunicationState <= TransmiteCheck;
count := 0;
countValue := 15;
end if;
when TransmiteCheck =>
if pback = '0' then
count := 0;
countValue := 1;
pbdata <= (others => 'Z');
CommunicationState <= PreparingToReceiveData;
else
if count < countValue then
count := count + 1;
else
CommunicationState <= Waiting;
errorCount := errorCount + 1;
errorBuf(0) <= '1';
end if;
end if;
when PreparingToReceiveData =>
if count < countValue then
count := count + 1;
else
pbdir <= b"00";
pbclk <= '0';
count := 0;
countValue := 15;
CommunicationState <= ReceiveData;
end if;
when ReceiveData =>
if pback = '1' then
pbclk <= '1';
dataTemp <= pbdata;
CommunicationState <= ReceiveCheck;
count := 0;
countValue := 15;
else
if count < countValue then
count := count + 1;
else
CommunicationState <= Waiting;
errorCount := errorCount + 1;
errorBuf(1) <= '1';
end if;
end if;
when ReceiveCheck =>
if pback = '0' then
if pbdata = not dataTemp then
memoryData(position) <= dataTemp(15 downto 8);
memoryData(position + 1) <= dataTemp(7 downto 0);
controlBuf <= memoryAddress(position);
CommunicationState <= Timeout;
count := 0;
pbce <= '1';
countValue := 5;
if position + 1 < conv_integer(cmdBuf(7 downto 0)) then
position := position + 2;
else
position := 0;
circleCounter := circleCounter + 1;
end if;
else
CommunicationState <= Waiting;
errorCount := errorCount + 1;
errorBuf(2) <= '1';
end if;
else
if count < countValue then
count := count + 1;
else
CommunicationState <= Waiting;
errorCount := errorCount + 1;
errorBuf(3) <= '1';
end if;
end if;
when Timeout =>
if count < countValue then
count := count + 1;
else
CommunicationState <= Waiting;
end if;
when others => CommunicationState <= Waiting;
end case;
else
pbclk <= '1';
pbce <= '1';
pbdata <= (others =>'Z');
pbdir <= b"11";
position := 0;
errorCount := 0;
errorBuf <= (others => '0');
CommunicationState <= Waiting;
end if;
end if;
end process;
end behavorial;