altera/MainController/RAM9X8_ParallelBusMaster.vhd

269 lines
9.2 KiB
VHDL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;